/*=============================================================================
D3DHWShader.cpp : D3D specific shaders support.
Copyright (c) 2001-2005 Crytek Studios. All Rights Reserved.

Revision history:
* Created by Honich Andrey

=============================================================================*/

#include "StdAfx.h"
#include "DriverD3D.h"
#include "I3DEngine.h"
#include <crc32.h>
#include "../Common/Shaders/RemoteCompiler.h"
#include "D3DLightPropagationVolume.h"
#include "../Common/PostProcess/PostEffects.h"
#include "D3DPostProcess.h"
#include "RenderObjectDefines.h"
#include "ParticleParams.h"

#define MAX_PF_SAMPLERS		(4)

#ifdef WIN64
	#pragma warning(disable: 4244)
#endif

//=======================================================================


DEFINE_ALIGNED_DATA(Vec4, CHWShader_D3D::m_CurPSParams[MAX_CONSTANTS_PS], 16);
DEFINE_ALIGNED_DATA(Vec4, CHWShader_D3D::m_CurVSParams[MAX_CONSTANTS_VS], 16);





#ifndef XENON
#if defined (DIRECT3D9)
DEFINE_ALIGNED_DATA(Vec4, CHWShader_D3D::m_CurPSParamsI[16], 16);
DEFINE_ALIGNED_DATA(Vec4, CHWShader_D3D::m_CurVSParamsI[16], 16);
#elif defined (DIRECT3D10)
ID3D11Buffer **CHWShader_D3D::m_pCB[eHWSC_Num][CB_NUM];
ID3D11Buffer *CHWShader_D3D::m_pCurReqCB[eHWSC_Num][CB_NUM];
void *CHWShader_D3D::m_pCurDevCB[eHWSC_Num][CB_NUM];
Vec4 *CHWShader_D3D::m_pDataCB[eHWSC_Num][CB_NUM];
int CHWShader_D3D::m_nCurMaxVecs[eHWSC_Num][CB_NUM];
int CHWShader_D3D::m_nMax_PF_Vecs[2];
int CHWShader_D3D::m_nMax_SG_Vecs[2];
ID3D11Buffer *CHWShader_D3D::m_pLightCB[eHWSC_Num];
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstGS;
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstHS;
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstDS;
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstCS;
#endif
#endif
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstVS;
CHWShader_D3D::SHWSInstance *CHWShader_D3D::m_pCurInstPS;
CHWShader_D3D::SHWSInstance  CHWShader_D3D::ms_EmptySHWInstance;

std::vector<SCGParam> CHWShader_D3D::m_PF_Params[eHWSC_Num];
std::vector<SCGParam> CHWShader_D3D::m_SG_Params[eHWSC_Num];
std::vector<SCGParam> CHWShader_D3D::m_CM_Params[eHWSC_Num];
std::vector<STexSamplerRT> CHWShader_D3D::m_PF_Samplers;     // Per-frame samplers

CHWShader_D3D::InstanceMap CHWShader_D3D::m_SharedInsts;

std::vector<SShaderTechniqueStat> g_SelectedTechs;

int CHWShader_D3D::m_FrameObj;

bool CHWShader_D3D::ms_bInitShaders = true;

int CHWShader_D3D::m_PSParamsToCommit[256];
int CHWShader_D3D::m_NumPSParamsToCommit;
int CHWShader_D3D::m_VSParamsToCommit[256];
int CHWShader_D3D::m_NumVSParamsToCommit;

int CHWShader_D3D::m_nResetDeviceFrame = -1;
int CHWShader_D3D::m_nInstFrame = -1;

bool CHWShader_D3D::ms_LevelShaderCacheMiss = false;
float CHWShader_D3D::ms_LastLevelShaderCacheMiss = 0.0f;

SD3DShader *CHWShader::m_pCurPS;
SD3DShader *CHWShader::m_pCurVS;
SD3DShader *CHWShader::m_pCurGS;
SD3DShader *CHWShader::m_pCurDS;
SD3DShader *CHWShader::m_pCurHS;
SD3DShader *CHWShader::m_pCurCS;

FXShaderCache CHWShader::m_ShaderCache;
FXShaderDevCache CHWShader::m_ShaderDevCache;
FXShaderCacheNames CHWShader::m_ShaderCacheList;

//extern float fTime0;
//extern float fTime1;
//extern float fTime2;

int SD3DShader::Release(EHWShaderClass eSHClass, int nSize)
{
  m_nRef--;
  if (m_nRef)
		return m_nRef;
  void *pHandle = m_pHandle;
  delete this;
	if (!pHandle)
		return 0;
  if (eSHClass == eHWSC_Pixel)
    CHWShader_D3D::m_nDevicePSDataSize -= nSize;
  else
    CHWShader_D3D::m_nDeviceVSDataSize -= nSize;

#if defined (DIRECT3D9)
  if (eSHClass == eHWSC_Pixel)
    return ((IDirect3DPixelShader9*)pHandle)->Release();
  else
    return ((IDirect3DVertexShader9*)pHandle)->Release();
#elif defined (DIRECT3D10)
  if (eSHClass == eHWSC_Pixel)
    return ((ID3D11PixelShader*)pHandle)->Release();
  else
  if (eSHClass == eHWSC_Vertex)
    return ((ID3D11VertexShader*)pHandle)->Release();
#if !defined(PS3) && !defined (XENON) && !defined(CAFE)
  else
  if (eSHClass == eHWSC_Geometry)
    return ((ID3D11GeometryShader*)pHandle)->Release();
  else
  if (eSHClass == eHWSC_Geometry)
    return ((ID3D11GeometryShader*)pHandle)->Release();
  else
  if (eSHClass == eHWSC_Hull)
    return ((ID3D11HullShader*)pHandle)->Release();
  else
  if (eSHClass == eHWSC_Compute)
    return ((ID3D11ComputeShader*)pHandle)->Release();
  else
  if (eSHClass == eHWSC_Domain)
    return ((ID3D11DomainShader*)pHandle)->Release();
#endif
  else
  {
    assert(0);
    return 0;
  }
#endif
}

void CHWShader_D3D::SHWSInstance::BindNULL()
{







}

void CHWShader_D3D::SHWSInstance::Release(SShaderDevCache *pCache, bool bReleaseData)
{
  //SAFE_DELETE(m_pSamplers);
  //SAFE_DELETE(m_pBindVars);
  //SAFE_DELETE(m_pParams[0]);
  //SAFE_DELETE(m_pParams[1]);
  //SAFE_DELETE(m_pParams_Inst);
  if (m_nParams[0] >= 0)
    CGParamManager::FreeParametersGroup(m_nParams[0]);
  if (m_nParams[1] >= 0)
    CGParamManager::FreeParametersGroup(m_nParams[1]);
  if (m_nParams_Inst >= 0)
    CGParamManager::FreeParametersGroup(m_nParams_Inst);

  int nCount = -1;
  if (m_Handle.m_pShader)
  {
    if (m_eClass == eHWSC_Pixel)
    {
      SD3DShader *pPS = m_Handle.m_pShader;
      if (pPS)
      {
        if (CHWShader::m_pCurPS == pPS)
          BindNULL();
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurPS == pPS)
          CHWShader::m_pCurPS = NULL;
      }
    }
    else
    if (m_eClass == eHWSC_Vertex)
    {
      SD3DShader *pVS = m_Handle.m_pShader;
      if (pVS)
      {
        if (CHWShader::m_pCurVS == pVS)
          BindNULL();
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurVS == pVS)
          CHWShader::m_pCurVS = NULL;
      }
    }
#if !defined(PS3) && !defined (XENON) && !defined(CAFE)
    else
    if (m_eClass == eHWSC_Geometry)
    {
      SD3DShader *pGS = m_Handle.m_pShader;
      if (pGS)
      {
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurGS == pGS)
          CHWShader::m_pCurGS = NULL;
      }
    }
    else
    if (m_eClass == eHWSC_Hull)
    {
      SD3DShader *pHS = m_Handle.m_pShader;
      if (pHS)
      {
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurHS == pHS)
          CHWShader::m_pCurHS = NULL;
      }
    }
    else
    if (m_eClass == eHWSC_Compute)
    {
      SD3DShader *pCS = m_Handle.m_pShader;
      if (pCS)
      {
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurCS == pCS)
          CHWShader::m_pCurCS = NULL;
      }
    }
    else
    if (m_eClass == eHWSC_Domain)
    {
      SD3DShader *pDS = m_Handle.m_pShader;
      if (pDS)
      {
        nCount = m_Handle.Release(m_eClass, m_nDataSize);
        if (!nCount && CHWShader::m_pCurDS == pDS)
          CHWShader::m_pCurDS = NULL;
      }
    }
#endif
  }
#ifdef DIRECT3D10
  SAFE_DELETE_VOID_ARRAY(m_pShaderData);
#endif


  if (!nCount && pCache && !pCache->m_DeviceShaders.empty())
    pCache->m_DeviceShaders.erase(m_DeviceObjectID);
  m_Handle.m_pShader = NULL;
}


CHWShader_D3D::SHWSSharedList::~SHWSSharedList()
{
  uint32 i, j;
  for (i=0; i<m_SharedInsts.size(); i++)
  {
    SHWSSharedInstance *pSInst = &m_SharedInsts[i];
    for (j=0; j<pSInst->m_Insts.size(); j++)
    {
      SHWSInstance *pInst = &pSInst->m_Insts[j];
      pInst->Release();
    }
		pSInst->m_Insts.clear();
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
		pSInst->m_LookupMap.clear();
#endif
  }
}

bool CHWShader::IsAllReleased()
{
  bool bReleased = true;
  CCryNameTSCRC Name = CHWShader::mfGetClassName(eHWSC_Pixel);
  SResourceContainer *pRL = CBaseResource::GetResourcesForClass(Name);
  if (pRL && pRL->m_RList.size())
    bReleased = false;

  Name = CHWShader::mfGetClassName(eHWSC_Vertex);
  pRL = CBaseResource::GetResourcesForClass(Name);
  if (pRL && pRL->m_RList.size())
    bReleased = false;
  if (CHWShader_D3D::m_SharedInsts.size())
    bReleased = false;

  return bReleased;
}

void CHWShader_D3D::InitialiseContainers()
{
	uint32 i;
	for(i=0;i<eHWSC_Num;i++)
	{
		m_PF_Params[i].reserve(8);
		m_SG_Params[i].reserve(8);
		m_CM_Params[i].reserve(8);
	}
	m_PF_Samplers.reserve(MAX_PF_SAMPLERS);  
}

void CHWShader_D3D::ShutDown()
{
  CCryNameTSCRC Name;
  SResourceContainer *pRL;

  // First make sure all HW and FX shaders are released
  Name = CHWShader::mfGetClassName(eHWSC_Vertex);
  pRL = CBaseResource::GetResourcesForClass(Name);
  if (pRL)
  {
    ResourcesMapItor itor;
    for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
    {
      CHWShader *vsh = (CHWShader *)itor->second;
      if (vsh)
        return;
    }
    pRL->m_RList.clear();
    pRL->m_AvailableIDs.clear();
  }

  Name = CHWShader::mfGetClassName(eHWSC_Pixel);
  pRL = CBaseResource::GetResourcesForClass(Name);
  if (pRL)
  {
    ResourcesMapItor itor;
    for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
    {
      CHWShader *psh = (CHWShader *)itor->second;
      if (psh)
        return;
    }
    pRL->m_RList.clear();
    pRL->m_AvailableIDs.clear();
  }

  Name = CShader::mfGetClassName();
  pRL = CBaseResource::GetResourcesForClass(Name);
  if (pRL)
  {
    ResourcesMapItor itor;
    int nNonReleased = 0;
    for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
    {
      CShader *sh = (CShader *)itor->second;
      if (!sh->m_DerivedShaders)
        nNonReleased++;
    }
    if (!pRL->m_RMap.size())
    {
      pRL->m_RList.clear();
      pRL->m_AvailableIDs.clear();
    }
  }

  // Delete all shared instances
  CHWShader_D3D::InstanceMapItor itInst;
  for (itInst=CHWShader_D3D::m_SharedInsts.begin(); itInst!=CHWShader_D3D::m_SharedInsts.end(); itInst++)
  {
    CHWShader_D3D::SHWSSharedList *pInstSL = itInst->second;
    SAFE_DELETE(pInstSL);
  }
  CHWShader_D3D::m_SharedInsts.clear();

  for (int i=0; i<eHWSC_Num; i++)
  {
    stl::free_container(m_CM_Params[i]);
    stl::free_container(m_PF_Params[i]);
    stl::free_container(m_SG_Params[i]);
  }
	stl::free_container(m_PF_Samplers);

  InstanceMapItor it;
	//FIXME: it crashes
/*  for (it=m_SharedInsts.begin(); it!=m_SharedInsts.end(); it++)
  {
    SHWSSharedList *pL = it->second;
    SAFE_DELETE(pL);
  }
*/

  stl::free_container(m_SharedInsts); 

	{
		Name = mfGetClassName(eHWSC_Vertex);
		pRL = CBaseResource::GetResourcesForClass(Name);
		if (pRL)
		{
			ResourcesMapItor itor;
			for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
			{
				CHWShader_D3D *vsh = (CHWShader_D3D *)itor->second;
				if (vsh)
					vsh->m_EntryFuncSharedItor = m_SharedInsts.end();
			}
		}

		Name = mfGetClassName(eHWSC_Pixel);
		pRL = CBaseResource::GetResourcesForClass(Name);
		if (pRL)
		{
			ResourcesMapItor itor;
			for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
			{
				CHWShader_D3D *psh = (CHWShader_D3D *)itor->second;
				if (psh)
					psh->m_EntryFuncSharedItor = m_SharedInsts.end();
			}
		}
	}

  gRenDev->m_cEF.m_Bin.mfReleaseFXParams();

  while (!m_ShaderCache.empty())
  {
    SShaderCache *pC = m_ShaderCache.begin()->second;
    SAFE_RELEASE(pC);
  }
  m_ShaderCacheList.clear();
  g_SelectedTechs.clear();
  CGParamManager::Shutdown();
}

#if defined (DIRECT3D10) || defined(PS3)

inline bool sCompareInstParams(const SCGParam&a, const SCGParam &b)
{
  return (a.m_dwBind < b.m_dwBind);
}

std::vector<SCGParam> sMergedParams;
void CHWShader::MergeInstanceParams(std::vector<SCGParam> *pParams)
{
  sMergedParams.resize(0);
  int i, j, n;
  for (i=0; i<m_RegisteredFX.size(); i++)
  {
    CShader *pFX = m_RegisteredFX[i];
		if (pFX)
		{
			for (j=0; j<pFX->m_InstParams.size(); j++)
			{
				SCGParam& pr = pFX->m_InstParams[j];
				for (n=0; n<sMergedParams.size(); n++)
				{
					SCGParam &p = sMergedParams[n];
					if (p.m_eCGParamType == pr.m_eCGParamType)
					{
						if (pr.m_dwCBufSlot > 0)
						{
							p.m_dwCBufSlot = pr.m_dwCBufSlot;
							p.m_dwBind = pr.m_dwBind;
						}
						break;
					}
				}
				if (n == sMergedParams.size())
				{
					sMergedParams.push_back(pr);
				}
			}
		}
  }

  if (pParams)
  {
    for (i=0; i<pParams->size(); i++)
    {
      SCGParam& p = (*pParams)[i];
      if (p.m_dwCBufSlot != CB_STATIC_INSTANCE)
        continue;
      assert(p.m_dwBind>=0 && p.m_dwBind < 10);
      for (j=0; j<sMergedParams.size(); j++)
      {
        SCGParam& pr = sMergedParams[j];
        if (pr.m_eCGParamType == p.m_eCGParamType)
        {
          assert(pr.m_dwBind == p.m_dwBind);
          if (pr.m_dwBind == p.m_dwBind)
          {
            pr.m_dwCBufSlot = p.m_dwCBufSlot;
            pr.m_nParameters = p.m_nParameters;
          }
          break;
        }
      }
      if (j == sMergedParams.size())
        sMergedParams.push_back(p);
    }
  }
  std::sort(sMergedParams.begin(), sMergedParams.end(), sCompareInstParams);

  uint32 nMaskCB = 0;
  for (j=0; j<sMergedParams.size(); j++)
  {
    SCGParam& pr = sMergedParams[j];
    if (pr.m_dwCBufSlot > 0)
      nMaskCB |= (1<<pr.m_dwBind);
  }

  int nInstParams = sMergedParams.size();
  for (i=0; i<m_RegisteredFX.size(); i++)
  {
    CShader *pFX = m_RegisteredFX[i];
		if (pFX)
		{
    	pFX->m_InstParams = sMergedParams;
    	pFX->m_nMaskCB = nMaskCB;
		}
  }
}

void CShader::UnregisterHW(CHWShader *pHW)
{
  assert(gRenDev->m_pRT->IsRenderThread());
  if (pHW->m_eSHClass != eHWSC_Vertex)
    return;
  int i;
  for (i=0; i<pHW->m_RegisteredFX.size(); i++)
  {
    CShader *pFX = pHW->m_RegisteredFX[i];
    if (pFX == this)
    {
      pHW->m_RegisteredFX.erase(pHW->m_RegisteredFX.begin()+i);
      break;
    }
  }
}

void CHWShader::RegisterFX(CShader *pFX,  std::vector<SCGParam> *pParams)
{
  int i;
  assert(gRenDev->m_pRT->IsRenderThread());
  for (i=0; i<m_RegisteredFX.size(); i++)
  {
    if (pFX == m_RegisteredFX[i])
      break;
  }
  if (i == m_RegisteredFX.size())
    m_RegisteredFX.push_back(pFX);
  MergeInstanceParams(pParams);
}
#endif

CHWShader *CHWShader::mfForName(const char *name, const char *nameSource, uint32 CRC32, const char *szEntryFunc, EHWShaderClass eClass, TArray<uint32>& SHData, FXShaderToken *pTable, uint32 dwType, CShader *pFX, uint64 nMaskGen, uint64 nMaskGenFX)
{
//	LOADING_TIME_PROFILE_SECTION(iSystem);
	if (!name || !name[0])
    return NULL;

	MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Shader, 0, "%s", name);

  CHWShader_D3D *pSH = NULL;
	stack_string strName = name;
  CCryNameTSCRC className = mfGetClassName(eClass);
  stack_string AddStr;

  if (nMaskGen)
  {



    strName += AddStr.Format("(%I64x)", nMaskGen);

  }
  if (CParserBin::m_nPlatform == SF_PS3)
    strName += AddStr.Format("(P)");
  else
  if (CParserBin::m_nPlatform == SF_D3D10)
    strName += AddStr.Format("(X0)", nMaskGen);
  else
  if (CParserBin::m_nPlatform == SF_D3D11)
    strName += AddStr.Format("(X1)", nMaskGen);
  else
  if (CParserBin::m_nPlatform == SF_XENON)
    strName += AddStr.Format("(X)");
	else
		if (CParserBin::m_nPlatform == SF_CAFE)
			strName += AddStr.Format("(C)", nMaskGen);

  CCryNameTSCRC Name = strName.c_str();
  CBaseResource *pBR = CBaseResource::GetResource(className, Name, false);
  if (!pBR)
  {
    pSH = new CHWShader_D3D;
    pSH->m_Name = strName.c_str();
    pSH->m_NameSourceFX = nameSource;
    pSH->Register(className, Name);
    pSH->m_EntryFunc = szEntryFunc;
    pSH->mfFree(CRC32);
#if defined (DIRECT3D10) || defined(PS3)
    if (eClass == eHWSC_Vertex)
      pSH->RegisterFX(pFX, NULL);
#endif

#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
		// do we want to use lookup table for faster searching of shaders
		if (CRenderer::CV_r_shadersuseinstancelookuptable)
		{
			pSH->m_bUseLookUpTable = true;
		}
#endif
  }
  else
  {
    pSH = (CHWShader_D3D *)pBR;
    pSH->AddRef();
#if defined (DIRECT3D10) || defined(PS3)
    if (eClass == eHWSC_Vertex)
      pSH->RegisterFX(pFX, NULL);
#endif
    if (pSH->m_CRC32 == CRC32)
    {
      if (pTable && gRenDev->m_cEF.m_eCacheMode != eSC_BuildPerLevel && !CRenderer::CV_r_shadersnocompile)
      {
        FXShaderToken *pMap = pTable;
        TArray<uint32> *pData = &SHData;
        pSH->mfGetCacheTokenMap(pMap, pData, pSH->m_nMaskGenShader);
      }
      return pSH;
    }
    pSH->mfFree(CRC32);
    pSH->m_CRC32 = CRC32;
  }

  if (CParserBin::m_bEditable)
  {
    if (pTable)
      pSH->m_TokenTable = *pTable;
    pSH->m_TokenData = SHData;
  }

  /*if (pTable)
  {
    TArray<char> sNewScr;
    CParserBin::ConvertToAscii(&SHData[0], SHData.size(), *pTable, sNewScr);
  #undef fopen
    FILE *fp = fopen(SYS_APP_HOME"/test.txt", "w");
  #define fopen WrappedFopen
    if (fp)
    {
      gEnv->pCryPak->FPrintf(fp, "%s", &sNewScr[0]);
      gEnv->pCryPak->FClose (fp);
    }
  }*/

  pSH->m_dwShaderType = dwType;
  pSH->m_eSHClass = eClass;
  pSH->m_nMaskGenShader = nMaskGen;
  pSH->m_nMaskGenFX = nMaskGenFX;
  pSH->m_CRC32 = CRC32;

  pSH->mfConstructFX(pTable, &SHData);

  return pSH;
}


void CHWShader_D3D::SetTokenFlags(uint32 nToken)
{
  switch (nToken)
  {
  case eT__LT_LIGHTS:
    m_Flags |= HWSG_SUPPORTS_LIGHTING;
    break;
  case eT__LT_0_TYPE:
  case eT__LT_1_TYPE:
  case eT__LT_2_TYPE:
  case eT__LT_3_TYPE:
    m_Flags |= HWSG_SUPPORTS_MULTILIGHTS;
    break;
  case eT__TT0_TCM:
  case eT__TT1_TCM:
  case eT__TT2_TCM:
  case eT__TT3_TCM:
  case eT__TT0_TCG_TYPE:
  case eT__TT1_TCG_TYPE:
  case eT__TT2_TCG_TYPE:
  case eT__TT3_TCG_TYPE:
  case eT__TT0_TCPROJ:
  case eT__TT1_TCPROJ:
  case eT__TT2_TCPROJ:
  case eT__TT3_TCPROJ:
  case eT__TT0_TCUBE:
  case eT__TT1_TCUBE:
  case eT__TT2_TCUBE:
  case eT__TT3_TCUBE:
    m_Flags |= HWSG_SUPPORTS_MODIF;
    break;
  case eT__VT_TYPE:
    m_Flags |= HWSG_SUPPORTS_VMODIF;
    break;
  case eT__FT_TEXTURE:
    m_Flags |= HWSG_FP_EMULATION;
    break;
  }
}

uint64 CHWShader_D3D::CheckToken(uint32 nToken)
{
  uint64 nMask = 0;
  SShaderGen *pGen = gRenDev->m_cEF.m_pGlobalExt;
  uint32 i;
  for (i=0; i<pGen->m_BitMask.Num(); i++)
  {
    SShaderGenBit *bit = pGen->m_BitMask[i];
    if (!bit)
      continue;

    if (bit->m_dwToken == nToken)
    {
      nMask |= bit->m_Mask;
      break;
    }
  }
  if (!nMask)
    SetTokenFlags(nToken);

  return nMask;
}

uint64 CHWShader_D3D::CheckIfExpr_r(uint32 *pTokens, uint32& nCur, uint32 nSize)
{
  uint64 nMask = 0;

  while (nCur < nSize)
  {
    int nRecurs = 0;
    uint32 nToken = pTokens[nCur++];
    if (nToken == eT_br_rnd_1) // check for '('
    {
      uint32 tmpBuf[64];
      int n = 0;
      int nD = 0;
      while (true)
      {
        nToken = pTokens[nCur];
        if (nToken == eT_br_rnd_1) // check for '('
          n++;
        else
        if (nToken == eT_br_rnd_2) // check for ')'
        {
          if (!n)
          {
            tmpBuf[nD] = 0;
            nCur++;
            break;
          }
          n--;
        }
        else
        if (nToken == 0)
          return nMask;
        tmpBuf[nD++] = nToken;
        nCur++;
      }
      if (nD)
      {
        uint32 nC = 0;
        nMask |= CheckIfExpr_r(tmpBuf, nC, nSize);
      }
    }
    else
    {
      bool bNeg = false;
      if (nToken == eT_excl)
      {
        bNeg = true;
        nToken = pTokens[nCur++];
      }
      nMask |= CheckToken(nToken);
    }
    nToken = pTokens[nCur];
    if (nToken == eT_or)
    {
      nCur++;
      assert (pTokens[nCur] == eT_or);
      if (pTokens[nCur] == eT_or)
        nCur++;
    }
    else
    if (nToken == eT_and)
    {
      nCur++;
      assert (pTokens[nCur] == eT_and);
      if (pTokens[nCur] == eT_and)
        nCur++;
    }
    else
      break;
  }
  return nMask;
}

void CHWShader_D3D::mfConstructFX_Mask_RT(FXShaderToken *Table, TArray<uint32>* pSHData)
{
  assert(gRenDev->m_cEF.m_pGlobalExt);
  m_nMaskAnd_RT = 0;
  m_nMaskOr_RT = 0;
  if (!gRenDev->m_cEF.m_pGlobalExt)
    return;
  SShaderGen *pGen = gRenDev->m_cEF.m_pGlobalExt;

  if (m_Flags & HWSG_SHARED)
  {
    assert(!pSHData->empty());
    uint32 *pTokens = &(*pSHData)[0];
    uint32 nSize = pSHData->size();
    uint32 nCur = 0;
    while (nCur < nSize)
    {
      uint32 nTok = CParserBin::NextToken(pTokens, nCur, nSize-1);
      if (!nTok)
        continue;
      if (nTok < eT_if || nTok > eT_elif)
        SetTokenFlags(nTok);
    }

    if (m_dwShaderType)
    {
      for (uint32 i=0; i<pGen->m_BitMask.Num(); i++)
      {
        SShaderGenBit *bit = pGen->m_BitMask[i];
        if (!bit)
          continue;
        uint32 j;
        if (bit->m_PrecacheNames.size())
        {
          for (j=0; j<bit->m_PrecacheNames.size(); j++)
          {
            if (m_dwShaderType == bit->m_PrecacheNames[j])
            {
              m_nMaskAnd_RT |= bit->m_Mask;
              break;
            }
          }
        }
      }
    }
    mfSetDefaultRT(m_nMaskAnd_RT, m_nMaskOr_RT);
  }
  else
  {
    assert(!pSHData->empty());
    uint32 *pTokens = &(*pSHData)[0];
    uint32 nSize = pSHData->size();
    uint32 nCur = 0;
    while (nCur < nSize)
    {
      uint32 nTok = CParserBin::NextToken(pTokens, nCur, nSize-1);
      if (!nTok)
        continue;
      if (nTok >= eT_if && nTok <= eT_elif)
        m_nMaskAnd_RT |= CheckIfExpr_r(pTokens, nCur, nSize);
      else
        SetTokenFlags(nTok);
    }

    // Reset any RT bits for this shader if this shader type is not existing for specific bit
    // See Runtime.ext file
    if (m_dwShaderType)
    {
      for (uint32 i=0; i<pGen->m_BitMask.Num(); i++)
      {
        SShaderGenBit *bit = pGen->m_BitMask[i];
        if (!bit)
          continue;
        if (bit->m_Flags & SHGF_RUNTIME)
          continue;

        uint32 j;
        if (bit->m_PrecacheNames.size())
        {
          for (j=0; j<bit->m_PrecacheNames.size(); j++)
          {
            if (m_dwShaderType == bit->m_PrecacheNames[j])
              break;
          }
          if (j == bit->m_PrecacheNames.size())
            m_nMaskAnd_RT &= ~bit->m_Mask;
        }
        else
          m_nMaskAnd_RT &= ~bit->m_Mask;
      }
    }
    mfSetDefaultRT(m_nMaskAnd_RT, m_nMaskOr_RT);
  }
}

void CHWShader_D3D::mfConstructFX(FXShaderToken* Table, TArray<uint32>* pSHData)
{
  if (!strnicmp(m_EntryFunc.c_str(), "Common_", 7))
    m_Flags |= HWSG_SHARED;
  if (!strnicmp(m_EntryFunc.c_str(), "Sync_", 5))
    m_Flags |= HWSG_SYNC;

  if (!pSHData->empty())
    mfConstructFX_Mask_RT(Table, pSHData);
  else
  {
    m_nMaskAnd_RT = -1;
    m_nMaskOr_RT = 0;
  }

  if (Table && gRenDev->m_cEF.m_eCacheMode != eSC_BuildPerLevel && !CRenderer::CV_r_shadersnocompile)
  {
    FXShaderToken *pMap = Table;
    TArray<uint32> *pData = pSHData;
    mfGetCacheTokenMap(pMap, pData, m_nMaskGenShader);   // Store tokens
  }
}

bool CHWShader_D3D::mfPrecache(SShaderCombination& cmb, bool bForce, bool bFallback, bool bCompressedOnly, CShader *pSH, SRenderShaderResources *pRes)
{
  assert(gRenDev->m_pRT->IsRenderThread());

  bool bRes = true;

  if (CRenderer::CV_r_shadersnocompile && !bForce)
    return bRes;

  uint64 AndRTMask = 0;
  uint64 OrRTMask = 0;
  mfSetDefaultRT(AndRTMask, OrRTMask);
  SShaderCombIdent Ident;
  Ident.m_RTMask = cmb.m_RTMask & AndRTMask | OrRTMask;
  Ident.m_MDVMask = cmb.m_MDVMask;
  if (m_eSHClass == eHWSC_Pixel)
    Ident.m_MDVMask = CParserBin::m_nPlatform;
  if (m_Flags & HWSG_SUPPORTS_MULTILIGHTS)
    Ident.m_LightMask = 1;
  Ident.m_GLMask = m_nMaskGenShader;
  uint32 nFlags = HWSF_PRECACHE;
  if (m_eSHClass == eHWSC_Pixel && pRes)
  {
    SHWSInstance *pInst = mfGetInstance(pSH, Ident, HWSF_PRECACHE_INST);
    pInst->m_bFallback = bFallback;
    int nResult = mfCheckActivation(pSH, pInst, HWSF_PRECACHE);
    if (!nResult)
      return bRes;
    mfUpdateSamplers();
    pInst->m_fLastAccess = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_RealTime;
    Ident.m_MDMask = gRenDev->m_RP.m_FlagsShader_MD & ~HWMD_TCMASK;
  }
  if (m_eSHClass == eHWSC_Pixel && gRenDev->m_RP.m_pShaderResources)
    Ident.m_MDMask &= ~HWMD_TCMASK;

  if (Ident.m_MDMask || bForce)
  {
    SHWSInstance *pInst = mfGetInstance(pSH, Ident, HWSF_PRECACHE_INST);
    pInst->m_bFallback = bFallback;
    pInst->m_fLastAccess = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_RealTime;
    mfActivate(pSH, nFlags, NULL, NULL, bCompressedOnly);
  }

  return bRes;
}



//==============================================================================================

DynArray<SCGParamPool> CGParamManager::m_Pools;
std::vector<SCGParamsGroup> CGParamManager::m_Groups;
std::vector<uint32, stl::STLGlobalAllocator<uint32> > CGParamManager::m_FreeGroups;

SCGParamPool::SCGParamPool(int nEntries)
:	m_Params(new SCGParam[nEntries], nEntries)
{
}

SCGParamPool::~SCGParamPool()
{
	delete[] m_Params.begin();
}

SCGParamsGroup SCGParamPool::Alloc(int nEntries)
{
  SCGParamsGroup Group;

  alloc_info_struct *pAI = gRenDev->GetFreeChunk(nEntries, m_Params.size(), m_alloc_info, "CGParam");
  if (pAI)
  {
    Group.nParams = nEntries;
    Group.pParams = &m_Params[pAI->ptr];
  }

  return Group;
}

bool SCGParamPool::Free(SCGParamsGroup& Group)
{
  bool bRes = gRenDev->ReleaseChunk((int)(Group.pParams-m_Params.begin()), m_alloc_info);
  return bRes;
}

int CGParamManager::GetParametersGroup(SParamsGroup& InGr, int nId)
{
  std::vector<SCGParam>& InParams = nId > 1 ? InGr.Params_Inst : InGr.Params[nId];
  int32 i;
  int nParams = InParams.size();

	int nGroupSize = m_Groups.size();
  for (i=0; i<nGroupSize; i++)
  {
    SCGParamsGroup& Gr = m_Groups[i];
    if (Gr.nParams != nParams)
      continue;
    int j;
    for (j=0; j<nParams; j++)
    {
      if (InParams[j] != Gr.pParams[j])
        break;
    }
    if (j == nParams)
    {
      Gr.nRefCounter++;
      return i;
    }
  }

  SCGParamsGroup Group;
  SCGParamPool *pPool = NULL;
  for (i=0; i<m_Pools.size(); i++)
  {
    pPool = &m_Pools[i];
    Group = pPool->Alloc(nParams);
    if (Group.nParams)
      break;
  }
  if (!Group.pParams)
  {
    pPool = NewPool(PARAMS_POOL_SIZE);
    Group = pPool->Alloc(nParams);
  }
  assert(Group.pParams);
  if (!Group.pParams)
    return 0;
  Group.nPool = i;
  uint32 n = m_Groups.size();
  if (m_FreeGroups.size())
  {
    n = m_FreeGroups.back();
    m_FreeGroups.pop_back();
    m_Groups[n] = Group;
  }
  else
  {
    m_Groups.push_back(Group);
  }

  for (i=0; i<nParams; i++)
  {
    m_Groups[n].pParams[i] = InParams[i];
  }
  bool bGeneral = true;
  if (nId == 0)
  {
    for (i=0; i<nParams; i++)
    {
      SCGParam& Pr = InParams[i];
      if ((Pr.m_eCGParamType & 0xff) != ECGP_PM_Tweakable && 
          Pr.m_eCGParamType != ECGP_PM_MatDiffuseColor &&
          Pr.m_eCGParamType != ECGP_PM_MatSpecularColor &&
          Pr.m_eCGParamType != ECGP_PM_MatEmissiveColor)
      {
        bGeneral = false;
        break;
      }
    }
  }
  else
  if (nId == 1)
  {
    for (i=0; i<nParams; i++)
    {
      SCGParam& Pr = InParams[i];
      if (Pr.m_eCGParamType != ECGP_SI_AmbientOpacity && 
        Pr.m_eCGParamType != ECGP_SI_BendInfo &&
        Pr.m_eCGParamType != ECGP_Matr_SI_Obj)
      {
        bGeneral = false;
        break;
      }
    }
  }
  m_Groups[n].bGeneral = bGeneral;

  return n;
}

bool CGParamManager::FreeParametersGroup(int nIDGroup)
{
  assert(nIDGroup>=0 && nIDGroup<(int)m_Groups.size());
  if (nIDGroup<0 || nIDGroup>=(int)m_Groups.size())
    return false;
  SCGParamsGroup& Group = m_Groups[nIDGroup];
  Group.nRefCounter--;
  if (Group.nRefCounter)
    return true;
  assert(Group.nPool>=0 && Group.nPool<m_Pools.size());
  if (Group.nPool<0 || Group.nPool>=m_Pools.size())
    return false;
  SCGParamPool& Pool = m_Pools[Group.nPool];
  if (!Pool.Free(Group))
    return false;
  for (int i=0; i<Group.nParams; i++)
  {
    Group.pParams[i].m_Name.reset();
    SAFE_DELETE(Group.pParams[i].m_pData);
  }

	Group.nParams = 0;
	Group.nPool = 0;
	Group.pParams = 0;

  m_FreeGroups.push_back(nIDGroup);

  return true;
}

void CGParamManager::Init()
{
	m_FreeGroups.reserve(128); // Based on spear
	m_Groups.reserve(2048);
}
void CGParamManager::Shutdown()
{
  m_FreeGroups.clear();
  m_Pools.clear();
  m_Groups.clear();
}

SCGParamPool *CGParamManager::NewPool(int nEntries)
{
  return new(m_Pools.grow_raw()) SCGParamPool(nEntries);
}

//===========================================================================================================

const SWaveForm sWFX = SWaveForm(eWF_Sin, 0, 3.5f, 0, 0.2f);
const SWaveForm sWFY = SWaveForm(eWF_Sin, 0, 5.0f, 90.0f, 0.2f);

union UFloat4
{
  float f[4];


#if defined(_CPU_SSE)
  __m128 m128;
#endif
};

DEFINE_ALIGNED_DATA(UFloat4, sDataBuffer[32], 16);
DEFINE_ALIGNED_DATA(float, sTempData[32][4], 16);
DEFINE_ALIGNED_DATA(float, sMatrInstData[3][4], 16);


/*
void sTranspose(Matrix34A& m, Matrix44A *dst)
{
  dst->m00=m.m00;	dst->m01=m.m10;	dst->m02=m.m20;	dst->m03=0;
  dst->m10=m.m01;	dst->m11=m.m11;	dst->m12=m.m21;	dst->m13=0;
  dst->m20=m.m02;	dst->m21=m.m12;	dst->m22=m.m22;	dst->m23=0;
  dst->m30=m.m03;	dst->m31=m.m13;	dst->m32=m.m23;	dst->m33=1;
}
void sTranspose(Matrix34A& m, Matrix33 *dst)
{
  dst->m00=m.m00;	dst->m01=m.m10;	dst->m02=m.m20;
  dst->m10=m.m01;	dst->m11=m.m11;	dst->m12=m.m21;
  dst->m20=m.m02;	dst->m21=m.m12;	dst->m22=m.m22;
}
*/
namespace
{
  NO_INLINE void sIdentityLine(UFloat4 *sData)
  {
#ifndef XENON_INTRINSICS
    sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = 0.f; sData[0].f[3] = 1.0f;


#endif
  }
  NO_INLINE void sOneLine(UFloat4 *sData)
  {
#ifndef XENON_INTRINSICS
    sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = 1.f; sData[0].f[3] = 1.0f;


#endif
  }
  NO_INLINE void sZeroLine(UFloat4 *sData)
  {
#ifndef XENON_INTRINSICS
    sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = 0.f; sData[0].f[3] = 0.0f;


#endif
  }



  NO_INLINE float* sGetLightMatrix(UFloat4 *sData, CD3D9Renderer *r)
  {
    SLightPass *pLP = &r->m_RP.m_LPasses[r->m_RP.m_nCurLightPass];
    assert (pLP->nLights==1 && (pLP->pLights[0]->m_Flags & DLF_PROJECT));
    SRenderLight *pDL = pLP->pLights[0];		
    if (pDL && pDL->GetLightTexture())
    {
      Matrix44A ProjMatrixT;
      CShadowUtils::GetProjectiveTexGen(pDL, 0, &ProjMatrixT);
      //*(Matrix44 *)&sData[0].f[0] = pDL->m_ProjMatrix;
      alias_cast<Matrix44A*>(&sData[0])->Transpose(ProjMatrixT);
    }
    else
      alias_cast<Matrix44A*>(&sData[0])->SetIdentity();
    return &sData[0].f[0];
  }
  NO_INLINE CRendElementBase *sGetContainerRE0(CRendElementBase * pRE)
  {
    assert(pRE);		// someone assigned wrong shader - function should not be called then

    if(pRE->mfGetType() == eDATA_Mesh && ((CREMeshImpl*)pRE)->m_pRenderMesh->_GetVertexContainer())
    {
      assert(((CREMeshImpl*)pRE)->m_pRenderMesh->_GetVertexContainer()->m_Chunks.Count()>=1);
      return ((CREMeshImpl*)pRE)->m_pRenderMesh->_GetVertexContainer()->m_Chunks[0].pRE;
    }

    return pRE;
  }

  NO_INLINE float *sGetTerrainBase(UFloat4 *sData, CD3D9Renderer *r)
  {
    if(!r->m_RP.m_pRE)  
      return NULL;				// it seems the wrong material was assigned 

    // use render element from vertex container render mesh if available
    CRendElementBase *pRE = sGetContainerRE0(r->m_RP.m_pRE);

    if (pRE && pRE->m_CustomData)
    {
      float *pData;

      if(SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID]<=1)
        pData = (float *)pRE->m_CustomData;
      else
        pData = (float *)pRE->m_CustomData + 4;

      sData[0].f[0] = pData[2]; sData[0].f[1] = pData[0]; sData[0].f[2] = pData[1];

		// always set this. Vegetation needs it to calculate correct terrain colour.
		sData[0].f[3] = pData[3];
    }
	else
	{
		sZeroLine(sData);

		// always set this. Vegetation needs it to calculate correct terrain colour.
		sData[0].f[3] = gEnv->p3DEngine->GetTerrainTextureMultiplier();
	}

    return &sData[0].f[0];
  }
  NO_INLINE float *sGetTerrainLayerGen(UFloat4 *sData, CD3D9Renderer *r)
  {
    if(!r->m_RP.m_pRE)
      return NULL;				// it seems the wrong material was assigned 

    CRendElementBase *pRE = r->m_RP.m_pRE;

    float *pData = (float *)pRE->m_CustomData;
    if (pData)
    {
      sData[0].f[0] = pData[0]; sData[0].f[1] = pData[1]; sData[0].f[2] = pData[2]; sData[0].f[3] = pData[3];
      sData[1].f[0] = pData[4]; sData[1].f[1] = pData[5]; sData[1].f[2] = pData[6]; sData[1].f[3] = pData[7];
      sData[2].f[0] = pData[8]; sData[2].f[1] = pData[9]; sData[2].f[2] = pData[10]; sData[2].f[3] = pData[11];
      sData[3].f[0] = pData[12]; sData[3].f[1] = pData[13]; sData[3].f[2] = pData[14]; sData[3].f[3] = pData[15];
      return &sData[0].f[0];
    }
    else
      return NULL;
  }
	NO_INLINE float *sGetTerrainLayerSlope(UFloat4 *sData, CD3D9Renderer *r)
	{
		if(!r->m_RP.m_pRE)
			return NULL;				// it seems the wrong material was assigned 

		CRendElementBase *pRE = r->m_RP.m_pRE;

		float *pData = (float *)pRE->m_CustomData;
		if (pData)
		{
			sData[0].f[0] = pData[16];
			sData[0].f[1] = pData[17];
			sData[0].f[2] = pData[18];
			sData[0].f[3] = pData[18];
			return &sData[0].f[0];
		}
		else
			return NULL;
	}

  NO_INLINE float *sGetVoxTerrainAtlasInfo(UFloat4 *sData, CD3D9Renderer *r)
  {
    if(!r->m_RP.m_pRE)
      return NULL;

    CRendElementBase *pRE = r->m_RP.m_pRE;

    float *pData = (float *)pRE->m_CustomData;
    if (pData)
    {
      sData[0].f[0] = pData[0];   sData[0].f[1] = pData[1];   sData[0].f[2] = pData[2];   sData[0].f[3] = pData[3];
      sData[1].f[0] = pData[4];   sData[1].f[1] = pData[5];   sData[1].f[2] = pData[6];   sData[1].f[3] = pData[7];
      sData[2].f[0] = pData[8];   sData[2].f[1] = pData[9];   sData[2].f[2] = pData[10];  sData[2].f[3] = pData[11];
      sData[3].f[0] = pData[12];  sData[3].f[1] = pData[13];  sData[3].f[2] = pData[14];  sData[3].f[3] = pData[15];
      sData[4].f[0] = pData[16];  sData[4].f[1] = pData[17];  sData[4].f[2] = pData[18];  sData[4].f[3] = pData[19];
      sData[5].f[0] = pData[20];  sData[5].f[1] = pData[21];  sData[5].f[2] = pData[22];  sData[5].f[3] = pData[23];
      return &sData[0].f[0];
    }
    else
      return NULL;
  }
	float *sGetTexMatrix(UFloat4 *sData, CD3D9Renderer *r, const SCGParam *ParamBind)
	{
		DEFINE_ALIGNED_DATA_STATIC(Matrix44, m, 16);

		
		SHRenderTarget *pTarg = (SHRenderTarget *)(UINT_PTR)ParamBind->m_nID;
		//assert(pTarg);
		if (!pTarg)
			return NULL;
		SEnvTexture *pEnvTex = pTarg->GetEnv2D();
		//assert(pEnvTex && pEnvTex->m_pTex);
		if (!pEnvTex || !pEnvTex->m_pTex)
			return NULL;

		if ((pTarg->m_eUpdateType != eRTUpdate_WaterReflect) && r->m_RP.m_pCurObject->m_ObjFlags & FOB_TRANS_MASK)
      m = r->m_RP.m_pCurObject->m_II.m_Matrix * pEnvTex->m_Matrix;
    else
      m = pEnvTex->m_Matrix;
    m.Transpose();

    return m.GetData();
  }
  void sGetWind(UFloat4 *sData, CD3D9Renderer *r)
  { 
    Vec4 pWind( 0, 0, 0, 0 );
		SBending* pB;
		CRenderObject *pObj = r->m_RP.m_pCurObject;
		SRenderObjData *pOD = pObj->GetObjData(r->m_RP.m_nProcessThreadID);

		if (pOD && (pB = pOD->m_pBending))
		{
			pWind.x = pB->m_Waves[0].m_Level;
			pWind.y = pB->m_Waves[1].m_Level;

			// Get phase variation based on object id
			pWind.z = (float) ((int) pObj->m_pRenderNode)/ (float) (INT_MAX);
			pWind.z *= 100000.0f;
			pWind.z -= floorf( pWind.z );
			pWind.z *= 10.0f;

			pWind.w = Vec2(pWind.x, pWind.y).GetLength();
		}

    sData[0].f[0] = pWind.x;
    sData[0].f[1] = pWind.y;
    sData[0].f[2] = pWind.z;
    sData[0].f[3] = pWind.w;    
  }
  NO_INLINE void sGetRotGridScreenOff(UFloat4 *sData, CD3D9Renderer *r)
  {
    int iTempX, iTempY, iWidth, iHeight;
    r->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
    sData[0].f[0] = 1.0f / (float)iWidth;
    sData[0].f[1] = 0.f; 
    sData[0].f[2] = 0.f;
    sData[0].f[3] = 1.0f / (float)iHeight;
    //rotated grid    
    Vec4 t75 = Vec4(0.75f * sData[0].f[0], 0.75f * sData[0].f[1], 0.75f * sData[0].f[2], 0.75f * sData[0].f[3]);
    Vec4 t25 = Vec4(0.25f * sData[0].f[0], 0.25f * sData[0].f[1], 0.25f * sData[0].f[2], 0.25f * sData[0].f[3]);
    Vec2 rotX = Vec2(t75[0]+t25[2], t75[1]+t25[3]);
    Vec2 rotY = Vec2(t75[2]-t25[0], t75[3]-t25[1]); 
    sData[0].f[0] = rotX[0];     sData[0].f[1] = rotX[1];
    sData[0].f[2] = rotY[0];     sData[0].f[3] = rotY[1];
  }

  NO_INLINE float sGetMaterialLayersOpacity( UFloat4 *sData, CD3D9Renderer *r )
  {
    float fMaterialLayersOpacity = 1.0f;

    uint32 nResourcesNoDrawFlags = r->m_RP.m_pShaderResources->GetMtlLayerNoDrawFlags();
    if( (r->m_RP.m_pCurObject->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK) && !(nResourcesNoDrawFlags&MTL_LAYER_CLOAK) )
    {
      fMaterialLayersOpacity = ((float)((r->m_RP.m_pCurObject->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK)>> 8) / 255.0f);
      fMaterialLayersOpacity = min(1.0f, 4.0f * max( 1.0f - fMaterialLayersOpacity, 0.0f) ); 
    }

    return fMaterialLayersOpacity;
  }

  NO_INLINE void sGetScreenSize(UFloat4 *sData, CD3D9Renderer *r)
  {
    int iTempX, iTempY, iWidth, iHeight;
    r->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
#if defined(WIN32) || defined(WIN64)
    float w = (float) (iWidth > 1 ? iWidth : 1);
    float h = (float) (iHeight > 1 ? iHeight : 1);
#else
    float w = (float) iWidth;
    float h = (float) iHeight;
#endif
    sData[0].f[0] = w;
    sData[0].f[1] = h;
    sData[0].f[2] = 0.5f / w;
    sData[0].f[3] = 0.5f / h;
  }

	NO_INLINE void sGetIrregKernel(UFloat4 *sData, CD3D9Renderer *r)
	{
		int nSamplesNum = 1;





		switch (r->m_RP.m_nShaderQuality)
		{
		case eSQ_Low:
			nSamplesNum = 4;
			break;
		case eSQ_Medium:
			nSamplesNum = 8;
			break;
		case eSQ_High:
			nSamplesNum = 16;
			break;
		case eSQ_VeryHigh:
			nSamplesNum = 16;
			break;
		default:
			assert(0);
		}


		CShadowUtils::GetIrregKernel((float(*)[4])&sData[0], nSamplesNum);
	}

  NO_INLINE void sGetRegularKernel(UFloat4 *sData, CD3D9Renderer *r)
  {
    float fRadius = r->CV_r_shadow_jittering;
    float SHADOW_SIZE = 1024.f;

    const Vec4 regular_kernel[9]=
    {
      Vec4(-1, 1, 0, 0),
      Vec4( 0, 1, 0, 0),
      Vec4( 1, 1, 0, 0),
      Vec4(-1, 0, 0, 0),
      Vec4( 0, 0, 0, 0),
      Vec4( 1, 0, 0, 0),
      Vec4(-1, -1, 0, 0),
      Vec4( 0, -1, 0, 0),
      Vec4( 1, -1, 0, 0)
    };

    float fFilterRange = fRadius/SHADOW_SIZE;

    for (int32 nInd = 0; nInd<9; nInd++)
    {
        if ((nInd%2) == 0)
        {
          sData[nInd/2].f[0] = regular_kernel[nInd].x * fFilterRange;
          sData[nInd/2].f[1] = regular_kernel[nInd].y * fFilterRange;
        }
        else
        {
          sData[nInd/2].f[2] = regular_kernel[nInd].x * fFilterRange;;
          sData[nInd/2].f[3] = regular_kernel[nInd].y * fFilterRange;;
        }
    }

    /*float FilterRange = radius/SHADOW_SIZE;
    float FilterStep = 1.0f/SHADOW_SIZE;

    int32 nInd = 0;
    for (float y=-FilterRange; y<FilterRange; y+=FilterStep)
    {
      for (float x=-FilterRange; x<FilterRange; x+=FilterStep, ++nInd)
      {
        assert((nInd/2) <= 5);

        if ((nInd%2) == 0)
        {
          sData[nInd/2][0] = x;
          sData[nInd/2][1] = y;
        }
        else
        {
          sData[nInd/2][2] = x;
          sData[nInd/2][3] = y;
        }
      }
    }
    */
  }
	NO_INLINE void sGetBendInfo(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

		Vec4& vCurBending = *alias_cast<Vec4*>(&sData->f);

		CRenderObject * const __restrict pObj = rRP.m_pCurObject;
		SRenderObjData *pOD = pObj->GetObjData(r->m_RP.m_nProcessThreadID);

		// Set values to zero if no bending found - eg. trees created as geom entity and not vegetation,
		// these are still rendered with bending/detailbending enabled in shader
		// (very ineffective but they should not appear in real levels)

		const SBending* __restrict pBending;
		if (pOD && (pBending = pOD->m_pBending))
		{
			// Fast version of CShaderMan::EvalWaveForm (for bending)
			const float realTime = rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;

			const SWaveForm2& RESTRICT_REFERENCE wave0 = pBending->m_Waves[0];
			vCurBending.x = wave0.m_Level;
			if (wave0.m_Amp)
			{
				float cycles = realTime*wave0.m_Freq + wave0.m_Phase;
				vCurBending.x += wave0.m_Amp * rRP.FastTableSinCycles(cycles);
			}

			const SWaveForm2& RESTRICT_REFERENCE wave1 = pBending->m_Waves[1];
			vCurBending.y = wave1.m_Level;
			if (wave1.m_Amp)
			{
				float cycles = realTime*wave1.m_Freq + wave1.m_Phase;
				vCurBending.y += wave1.m_Amp * rRP.FastTableSinCycles(cycles);
			}

			vCurBending.z = 1.f;
			vCurBending.w = Vec2(vCurBending.x, vCurBending.y).GetLength() * 250.f;
		}
		else
			vCurBending = Vec4(0,0,0,0);
	}

  NO_INLINE Vec4 sGetVolumetricFogParams(CD3D9Renderer* r)
  {
    Vec4 pFogParams;

    I3DEngine* pEng = gEnv->p3DEngine;
    assert(pEng);

    Vec3 globalDensityParams(0,1,1);
    pEng->GetGlobalParameter(E3DPARAM_VOLFOG_GLOBAL_DENSITY, globalDensityParams);

    float globalDensity = globalDensityParams.x;
    if (!gRenDev->IsHDRModeEnabled())
      globalDensity *= globalDensityParams.y;

    Vec3 volFogHeightDensity(0,1,0);
    pEng->GetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY, volFogHeightDensity);
    volFogHeightDensity.y = clamp_tpl(volFogHeightDensity.y, 1e-5f, 1.0f);

    Vec3 volFogHeightDensity2(4000.0f,0,0);
    pEng->GetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY2, volFogHeightDensity2);
    volFogHeightDensity2.y = clamp_tpl(volFogHeightDensity2.y, 1e-5f, 1.0f);
    volFogHeightDensity2.x = volFogHeightDensity2.x < volFogHeightDensity.x + 1.0f ? volFogHeightDensity.x + 1.0f : volFogHeightDensity2.x;

    const float ha = volFogHeightDensity.x;
    const float hb = volFogHeightDensity2.x;

    const float da = volFogHeightDensity.y;
    const float db = volFogHeightDensity2.y;

    const float ga = logf(da);
    const float gb = logf(db);

    const float c = (gb - ga) / (hb - ha);
    const float o = ga - c * ha;

    const float viewerHeight = r->GetRCamera().Orig.z;

    globalDensity *= 0.01f; // multiply by 1/100 to scale value editor value back to a reasonable range

    pFogParams.x = c;
    pFogParams.y = 1.44269502f * globalDensity * expf(c * viewerHeight + o); // log2(e) = 1.44269502
    pFogParams.z = globalDensity;
    pFogParams.w = 1.0f - clamp_tpl(globalDensityParams.z, 0.0f, 1.0f);

    return pFogParams;
  }

	NO_INLINE Vec4 sGetVolumetricFogRampParams()
	{
		I3DEngine *pEng = gEnv->p3DEngine;
		
		Vec3 vfRampParams(0, 100.0f, 0);
		pEng->GetGlobalParameter(E3DPARAM_VOLFOG_RAMP, vfRampParams);

		vfRampParams.x = vfRampParams.x < 0 ? 0 : vfRampParams.x; // start
		vfRampParams.y = vfRampParams.y < vfRampParams.x + 0.1f ? vfRampParams.x + 0.1f : vfRampParams.y; // end
		vfRampParams.z = clamp_tpl(vfRampParams.z, 0.0f, 1.0f); // influence

		float invRampDist = 1.0f / (vfRampParams.y - vfRampParams.x);
		return Vec4(invRampDist, -vfRampParams.x * invRampDist, vfRampParams.z, -vfRampParams.z + 1.0f);
	}

	NO_INLINE void sGetFogColorGradientConstants(Vec4& fogColGradColBase, Vec4& fogColGradColDelta)
	{
		I3DEngine* pEng = gEnv->p3DEngine;

		Vec3 colBase = pEng->GetFogColor();
		fogColGradColBase = Vec4(colBase, 0);

		Vec3 colTop(colBase);
		pEng->GetGlobalParameter(E3DPARAM_FOG_COLOR2, colTop);
		fogColGradColDelta = Vec4(colTop - colBase, 0);
	}

	NO_INLINE Vec4 sGetFogColorGradientParams()
	{
		I3DEngine* pEng = gEnv->p3DEngine;

		Vec3 volFogHeightDensity(0,1,0);
		pEng->GetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY, volFogHeightDensity);

		Vec3 volFogHeightDensity2(4000.0f,0,0);
		pEng->GetGlobalParameter(E3DPARAM_VOLFOG_HEIGHT_DENSITY2, volFogHeightDensity2);
		volFogHeightDensity2.x = volFogHeightDensity2.x < volFogHeightDensity.x + 1.0f ? volFogHeightDensity.x + 1.0f : volFogHeightDensity2.x;

		Vec3 gradientCtrlParams(0,0.75f,0.5f);
		pEng->GetGlobalParameter(E3DPARAM_VOLFOG_GRADIENT_CTRL, gradientCtrlParams);

		const float colorHeightOffset = clamp_tpl(gradientCtrlParams.x, -1.0f, 1.0f);
		const float radialSize = -expf((1.0f - clamp_tpl(gradientCtrlParams.y, 0.0f, 1.0f)) * 14.0f) * 1.44269502f; // log2(e) = 1.44269502;
		const float radialLobe = 1.0f / clamp_tpl(gradientCtrlParams.z, 1.0f / 21.0f, 1.0f) - 1.0f;

		const float invDist = 1.0f / (volFogHeightDensity2.x - volFogHeightDensity.x);
		return Vec4(invDist, -volFogHeightDensity.x * invDist - colorHeightOffset, radialSize, radialLobe);
	}

	NO_INLINE Vec4 sGetFogColorGradientRadial(CD3D9Renderer* r)
	{
		I3DEngine* pEng = gEnv->p3DEngine;

		Vec3 fogColorRadial(0,0,0);
		pEng->GetGlobalParameter(E3DPARAM_FOG_RADIAL_COLOR, fogColorRadial);

		const CRenderCamera& rc = r->GetRCamera();
		const float invFarDist = 1.0f / rc.Far;

		return Vec4(fogColorRadial, invFarDist);
	}

	NO_INLINE Vec4 sGetVolumetricFogSunDir()
	{
		I3DEngine* pEng = gEnv->p3DEngine;
		return Vec4(pEng->GetSunDirNormalized(), 0);
	}

/*  float *sTranspose(Matrix34A& m)
  {
    static Matrix44A dst;
    dst.m00=m.m00;	dst.m01=m.m10;	dst.m02=m.m20;	dst.m03=0;
    dst.m10=m.m01;	dst.m11=m.m11;	dst.m12=m.m21;	dst.m13=0;
    dst.m20=m.m02;	dst.m21=m.m12;	dst.m22=m.m22;	dst.m23=0;
    dst.m30=m.m03;	dst.m31=m.m13;	dst.m32=m.m23;	dst.m33=1;

    return dst.GetData();
  }
  void sTranspose(Matrix44A& m, Matrix44A *dst)
  {
    dst->m00=m.m00;	dst->m01=m.m10;	dst->m02=m.m20;	dst->m03=m.m30;
    dst->m10=m.m01;	dst->m11=m.m11;	dst->m12=m.m21;	dst->m13=m.m31;
    dst->m20=m.m02;	dst->m21=m.m12;	dst->m22=m.m22;	dst->m23=m.m32;
    dst->m30=m.m03;	dst->m31=m.m13;	dst->m32=m.m23;	dst->m33=m.m33;
  }
*/
  void sGetMotionBlurData(UFloat4 *sData, CD3D9Renderer *r, const SInstanceInfo &instInfo)
  {
    // special motion blur instanced data:
    //  - contains (previous frame camera view) * (previous frame object matrix) 
    //  - merged transformation with object motion blur amount and shutter speed
  
		Matrix44A &CamPrevMat = CMotionBlur::GetPrevView();

    float fMotionBlurAmount( 1.0f ); // needs to match camera

    CRenderObject *pObj = r->m_RP.m_pCurObject;

		Matrix44A mObjCurr;
    mObjCurr.Transpose(instInfo.m_Matrix);   
      
		Matrix44A mObjPrev;							
		mObjPrev.Transpose(CMotionBlur::GetPrevObjToWorldMat(pObj));

		Matrix44A mCamObjCurr, mCamObjPrev;
		mCamObjCurr.Multiply(mObjCurr, r->m_CameraMatrix); 

		//if( pObj->m_ObjFlags & FOB_NEAREST )
		//	mCamObjPrev.Multiply(mObjPrev, r->m_CameraMatrixNearestPrev); 
		//else				
			mCamObjPrev.Multiply(mObjPrev, CamPrevMat); 

		float fExposureTime = CRenderer::CV_r_MotionBlurShutterSpeed * fMotionBlurAmount;

    // mk fix for time normalization

    // renormalize frametime to account for time scaling
    float fCurrFrameTime = gEnv->pTimer->GetFrameTime();      
    float fTimeScale = gEnv->pTimer->GetTimeScale();
    if (fTimeScale < 1.0f)
    {
      fTimeScale = max(0.0001f, fTimeScale);
      fCurrFrameTime /= fTimeScale; 
    }

    float fAlpha = 0.0f;
		if(fCurrFrameTime != 0.0f)
			fAlpha = fExposureTime / fCurrFrameTime;  

    if( CRenderer::CV_r_MotionBlurFrameTimeScale )
    {
      float fAlphaScale = iszero(fCurrFrameTime) ? 1.0f : min(1.0f, (1.0f / fCurrFrameTime) / ( 32.0f)); // attenuate motion blur for lower frame rates
      fAlpha *= fAlphaScale;
    }
	

		// Interpolate matrixes and position
		//Matrix33 pLerpedView = Matrix33(mCamObjCurr)*(1-fAlpha) + Matrix33(mCamObjPrev)*fAlpha;   
		//Vec3 pLerpedPos = mCamObjCurr.GetRow(3)*(1-fAlpha) + mCamObjPrev.GetRow(3) * fAlpha;     

		//// Compose final 'previous' viewProjection matrix
		//Matrix44 pLView = pLerpedView;
		//pLView.m30 = pLerpedPos.x;   
		//pLView.m31 = pLerpedPos.y;
		//pLView.m32 = pLerpedPos.z; 

		//mCamObjCurr = pLView;//mCamObjCurr * (1.0f - fAlpha) + mCamObjPrev * fAlpha;  
		mCamObjCurr = mCamObjPrev;
    mCamObjCurr.Transpose();

    float *pData = mCamObjCurr.GetData();
    // todo: use SSE
    sData[0].f[0] = pData[0]; sData[0].f[1] = pData[1]; sData[0].f[2] = pData[2]; sData[0].f[3] = pData[3];
    sData[1].f[0] = pData[4]; sData[1].f[1] = pData[5]; sData[1].f[2] = pData[6]; sData[1].f[3] = pData[7];
    sData[2].f[0] = pData[8]; sData[2].f[1] = pData[9]; sData[2].f[2] = pData[10]; sData[2].f[3] = pData[11];
  }

  void sGetTessParams(UFloat4 *sData, CD3D9Renderer *r)
  {
		// we want to achieve the edge length in pixels specified by CV_r_tessellationtrianglesize
		// therefore the tessfactor would depend on the viewportsize and CV_r_tessellationtrianglesize
		int iTempX, iTempY, iWidth, iHeight;
		r->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
		
		static const ICVar* pCV_e_TessellationMaxDistance( gEnv->pConsole->GetCVar( "e_TessellationMaxDistance") );
		const float fFOV = r->GetCamera().GetHorizontalFov();

		sData[0].f[0] = sqrtf(float(iWidth * iHeight)) / (fFOV * r->CV_r_tessellationtrianglesize);
		sData[0].f[1] = r->CV_r_displacementfactor;
		sData[0].f[2] = pCV_e_TessellationMaxDistance->GetFVal();
		sData[0].f[3] = 0.f;
  }

  void sGetCloakParams(UFloat4 *sData, CD3D9Renderer *r, const SInstanceInfo &instInfo)
  {
    CRenderObject *pObj = r->m_RP.m_pCurObject;
    static int nLastFrameID=-1;    
    static Matrix44A mCamObjCurr;    
    static Vec3 pCamPrevPos = Vec3(0,0,0);

    if( nLastFrameID != gRenDev->GetFrameID(true) )
    {
      // invert and get camera previous world space position
      Matrix44A CamPrevMatInv = CMotionBlur::GetPrevView();
			CamPrevMatInv.Invert();
      pCamPrevPos = CamPrevMatInv.GetRow(3);
      nLastFrameID = gRenDev->GetFrameID(true);
    }

    if (pObj)
    {
      Vec3 pObjPosWS = instInfo.m_Matrix.GetColumn(3);

      // Get amount of light on cpu - dont want to add more shader permutations - this might be useful for other stuff - expose
      float fLightAmount = 0.0f;
      for( uint32 nCurrDLight = 0; nCurrDLight < r->m_RP.m_DLights[r->m_RP.m_nProcessThreadID][SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID]-1].Num() ; ++nCurrDLight )
      {
        if ( pObj->m_DynLMMask[r->m_RP.m_nProcessThreadID] & (1<<nCurrDLight) )
        {
          SRenderLight *pDL = &r->m_RP.m_DLights[r->m_RP.m_nProcessThreadID][SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID]-1][nCurrDLight];

          // compute attenuation if not sun
          float fAttenuation = 1.0f;
          if( !(pDL->m_Flags & DLF_SUN) )
          {
            float fInvRadius = pDL->m_fRadius;
            if (fInvRadius <= 0)
              fInvRadius = 1.f;

            fInvRadius = 1.f / fInvRadius;

            // light position
            Vec3 pLightVec = pDL->m_Origin - pObjPosWS;

            // compute attenuation
            pLightVec *= fInvRadius;
            fAttenuation = clamp_tpl<float>(1.0f - (pLightVec.x * pLightVec.x + pLightVec.y * pLightVec.y + pLightVec.z * pLightVec.z), 0.0f, 1.0f);
          }

          fLightAmount += fAttenuation * ( (pDL->m_Color[0] + pDL->m_Color[1] + pDL->m_Color[2]) *0.33f );
        }
      }

      // Add ambient
      fLightAmount += (instInfo.m_AmbColor[0] + instInfo.m_AmbColor[1] + instInfo.m_AmbColor[2])*0.33f;

      // trying to match luminance bettwen hdr/non-hdr
      if( !CRenderer::CV_r_HDRRendering )
      {
        fLightAmount = 1.0f - expf( - fLightAmount );
        fLightAmount *= 2.5f;
      }
      else
        fLightAmount *= 0.25f;

			// Allow light override if this feature is needed indoors
			fLightAmount = max(CRenderer::CV_r_cloakMinLightValue,fLightAmount);
        
      // Get cloak blend amount from material layers
      float fCloakBlendAmount = ((pObj->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK)>>8)/255.0f;

      // Get instance speed 
      float fMotionBlurAmount( 0.3f ); 

      Matrix44A mObjCurr;
      mObjCurr.Transpose(instInfo.m_Matrix);   
      Matrix44A mObjPrev;
      SRenderObjData *pOD = pObj->GetObjData(r->m_RP.m_nProcessThreadID);
      assert(pOD);
      //if (pOD)
      //  mObjPrev.Transpose(pOD->m_prevMatrix);   
			mObjPrev.SetIdentity();

      Matrix44A mCamObjPrev;
      float fSpeedScale = 1.0f;

      mCamObjCurr = mObjCurr;
      mCamObjPrev = mObjPrev;

      // temporary solution for GC demo
      float fExposureTime = 0.0005f; //CRenderer::CV_r_MotionBlurShutterSpeed * fMotionBlurAmount; 

      // renormalize frametime to account for time scaling
      float fCurrFrameTime = gEnv->pTimer->GetFrameTime();      
      float fTimeScale = gEnv->pTimer->GetTimeScale();
      if (fTimeScale < 1.0f)
      {
        fTimeScale = max(0.0001f, fTimeScale);
        fCurrFrameTime /= fTimeScale; 
      }

      float fAlpha = 0.0f;
      if(fCurrFrameTime != 0.0f)
        fAlpha = fExposureTime / fCurrFrameTime;  
      
      mCamObjPrev = mCamObjCurr * (1.0f - fAlpha) + mCamObjPrev * fAlpha;  

			Vec3 camObjCurrPos = mCamObjCurr.GetRow(3);
      Vec3 pVelocity = camObjCurrPos - mCamObjPrev.GetRow(3);
      float fCurrSpeed = max( pVelocity.GetLength() - 0.01f, 0.0f);

      float fCloakFalloff = 1.0f;

			// Apply fade by distance feature to cloak
			if(pOD && r->CV_r_cloakFadeByDist && (pOD->m_nCustomFlags & COB_FADE_CLOAK_BY_DISTANCE))
			{
				float zoomFactor = RAD2DEG(gRenDev->GetCamera().GetFov()) * (1.0f/60.0f);
				Limit(zoomFactor,0.0f,1.0f);
				float objDistFromCamSq = (pObjPosWS - gRenDev->GetRCamera().Orig).GetLengthSquared() * zoomFactor;

				float minCloakScale = r->CV_r_cloakFadeMinValue;
				Limit(minCloakScale,0.0f,1.0f);
				if(objDistFromCamSq > r->CV_r_cloakFadeEndDistSq)
				{
					// Cloaked obj is further than fade end distance
					fCloakBlendAmount *= minCloakScale;
					fLightAmount *= minCloakScale;
				}
				else if(objDistFromCamSq > r->CV_r_cloakFadeStartDistSq)
				{
					// Cloak obj is between start and end fade params, so apply fade
					float fadeDistRange = r->CV_r_cloakFadeEndDistSq - r->CV_r_cloakFadeStartDistSq;
					if(fadeDistRange > 0.0f) // Avoid division by 0
					{
						float fadeScale = ((objDistFromCamSq - r->CV_r_cloakFadeStartDistSq) / fadeDistRange);
						float cloakAlpha = LERP(1.0f,minCloakScale,fadeScale);
						fCloakBlendAmount *= cloakAlpha;
						fLightAmount *= cloakAlpha;
					}
					else
					{
						fCloakBlendAmount *= minCloakScale;
						fLightAmount *= minCloakScale;
					}
				}

				if(!(pOD->m_nCustomFlags & COB_IGNORE_CLOAK_REFRACTION_COLOR))
				{
					fLightAmount *= r->CV_r_cloakFadeLightScale;
				}

        if(r->CV_r_cloakRefractionFadeByDist)
        {
				  float minCloakRefractionScale = r->CV_r_cloakRefractionFadeMinValue;
          // far away, use min value
				  if(objDistFromCamSq > r->CV_r_cloakRefractionFadeEndDistSq)
				  {
            fCloakFalloff = minCloakRefractionScale;
          }
          // in fade range
          else if(objDistFromCamSq > r->CV_r_cloakRefractionFadeStartDistSq)
          {
            float range = r->CV_r_cloakRefractionFadeEndDistSq - r->CV_r_cloakRefractionFadeStartDistSq;

            // ensure range is sane
            if(range > 0.0f)
            {
              float delta = ((objDistFromCamSq - r->CV_r_cloakRefractionFadeStartDistSq) / range);
              fCloakFalloff = LERP(1.0f,minCloakRefractionScale,delta);
            }
          }
          // really near by, we're already set to 1.0f so that's ok
          /*
          else
          {
          }
          */
        }
			}
			else
			{
				fLightAmount *= r->CV_r_cloakLightScale;
			}

			// Allow ability to control light scale during cloak transition
			if(fCloakBlendAmount < 1.0f)
			{
				fLightAmount *= r->CV_r_cloakTransitionLightScale;
			}

			const float cloakPaletteTexelOffset = 0.125f;
			float fCustomData = pOD? static_cast<float>(pOD->m_nCustomData) : 0.0f;
			float paletteColorChannel = clamp_tpl<float>(((fCustomData+1.0f)*0.25f) - cloakPaletteTexelOffset,0.0f,1.0f);
			float cloakSparksAlpha = CRenderer::CV_r_cloakSparksAlpha;
			if(pOD)
			{
				if(pOD->m_nCustomFlags & COB_CLOAK_INTERFERENCE)
				{
					cloakSparksAlpha = CRenderer::CV_r_cloakInterferenceSparksAlpha;
				}
				if(pOD->m_nCustomFlags & COB_CLOAK_HIGHLIGHT)
				{
					const float highlightAlpha = pOD->m_fTempVars[5];
					fLightAmount = LERP(fLightAmount,max(fLightAmount,CRenderer::CV_r_cloakHighlightStrength),highlightAlpha);
				}
			}

      sData[0].f[0] = fCloakFalloff;
			sData[0].f[1] = paletteColorChannel;
			sData[0].f[2] = fLightAmount;
			
			SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;
			sData[0].f[3] = fCloakBlendAmount * ((pRes)? pRes->CloakAmount():0);

			sData[1].f[0] = cloakSparksAlpha;
			memset(&sData[1].f[1], 0, sizeof(float)*3);
    }
		else
		{
			memset(sData[0].f, 0, sizeof(float)*4);
			memset(sData[1].f, 0, sizeof(float)*4);
		}
  }

  void sGetFrozenParams(UFloat4 *sData, CD3D9Renderer *r, const SInstanceInfo &instInfo)
  {
    CRenderObject *pObj = r->m_RP.m_pCurObject; 
    Vec4 frozenParams(0, 0, 0, 0);

    if (pObj)
    {
      // Get frost blend amount from material layers
      float fFrostBlendAmount = ((pObj->m_nMaterialLayers&MTL_LAYER_BLEND_DYNAMICFROZEN))/255.0f;

	  // to take COB_DISABLE_MOTIONBLUR into account which also sets g_HWSR_MaskBit[HWSR_NEAREST]
      //if( r->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[HWSR_NEAREST] )
      if( r->m_RP.m_ObjFlags & FOB_NEAREST )
        fFrostBlendAmount *= 0.5f;

      float fUseObjSpace = 0;//(pObj->m_ObjFlags & FOB_MTLLAYERS_OBJSPACE)? 1.0f : 0.0f;

      if (r->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[HWSR_SAMPLE4])
      {
        Vec3 pObjPosWS = instInfo.m_Matrix.GetColumn(3);

        // Get amount of light on cpu - dont want to add more shader permutations - this might be useful for other stuff - expose
        ColorF pLightAmount = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
        for( uint32 nCurrDLight = 0; nCurrDLight < r->m_RP.m_DLights[r->m_RP.m_nProcessThreadID][SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID]-1].Num() ; ++nCurrDLight )
        {
          if ( pObj->m_DynLMMask[r->m_RP.m_nProcessThreadID] & (1<<nCurrDLight) )
          {
            SRenderLight *pDL = &r->m_RP.m_DLights[r->m_RP.m_nProcessThreadID][SRendItem::m_RecurseLevel[r->m_RP.m_nProcessThreadID]-1][nCurrDLight];

            // compute attenuation if not sun
            float fAttenuation = 1.0f;
            if( !(pDL->m_Flags & DLF_SUN) )
            {
              float fInvRadius = pDL->m_fRadius;
              if (fInvRadius <= 0)
                fInvRadius = 1.f;

              fInvRadius = 1.f / fInvRadius;

              // light position
              Vec3 pLightVec = pDL->m_Origin - pObjPosWS;

              // compute attenuation	
              pLightVec *= fInvRadius;
              fAttenuation = clamp_tpl<float>(1.0f - (pLightVec.x * pLightVec.x + pLightVec.y * pLightVec.y + pLightVec.z * pLightVec.z), 0.0f, 1.0f);
            }

            pLightAmount += fAttenuation * pDL->m_Color;
          }
        }

        // Add ambient
        //pLightAmount += instInfo.m_AmbColor;

        frozenParams.x = pLightAmount[0];
        frozenParams.y = pLightAmount[1];
        frozenParams.z = pLightAmount[2];
        frozenParams.w = fFrostBlendAmount;
      }
      else
      {
        frozenParams.x = frozenParams.y = frozenParams.z = fFrostBlendAmount;
        frozenParams.w = fUseObjSpace;
      }
    }

    sData[0].f[0] = frozenParams.x;
    sData[0].f[1] = frozenParams.y;
    sData[0].f[2] = frozenParams.z;
    sData[0].f[3] = frozenParams.w;
  }
  void sGetSnowVolumeParams(UFloat4 *sData, CD3D9Renderer *r, const SInstanceInfo &instInfo)
  {
	  const N3DEngineCommon::SSnowInfo & snowVolParams = r->m_p3DEngineCommon.m_SnowInfo;
	  uint32 nThreadID = gRenDev->m_RP.m_nProcessThreadID;

	  // Disabled by default.
	  sData[0].f[0] = 0;
	  sData[1].f[3] = 0;

	  bool bSnowEnabled = (CRenderer::CV_r_snow > 0)
							&& (snowVolParams.m_fSnowAmount > 0.05f
							|| snowVolParams.m_fFrostAmount > 0.05f
							|| snowVolParams.m_fSurfaceFreezing > 0.05f)
							&& snowVolParams.m_fRadius > 0.05f;


	  // Snow is globally enabled (for glossiness/dynamic object encoding).
	  sData[1].f[3] = bSnowEnabled;

	  sData[0].f[1] = snowVolParams.m_fSnowAmount;
	  sData[0].f[2] = snowVolParams.m_fFrostAmount;
	  sData[0].f[3] = snowVolParams.m_fSurfaceFreezing;

	  sData[1].f[0] = snowVolParams.m_vWorldPos.x;
	  sData[1].f[1] = snowVolParams.m_vWorldPos.y;
	  sData[1].f[2] = snowVolParams.m_vWorldPos.z;

	  // Check if object is dynamic or static and whether it should accept snow.
	  CRenderObject *pObj = r->m_RP.m_pCurObject; 
	  if(pObj)
	  {
		  Vec3 vObjectPos = pObj->GetTranslation();
		  float fObjToVol = vObjectPos.GetSquaredDistance( snowVolParams.m_vWorldPos );
		  float fObjectHeight = vObjectPos.z;

		  const bool bIsTerrain = gRenDev->m_RP.m_pShader && gRenDev->m_RP.m_pShader->GetShaderType() == eST_Terrain;
		  bool bIsInRange = (fObjToVol <= snowVolParams.m_fRadius*snowVolParams.m_fRadius * 2.0f);

		  // Get the render element.
		  CRendElementBase *pRE = r->m_RP.m_pRE;
		  if (pRE)
		  {
			  // Do a bounding box intersection test to determine whether we should apply snow or not.
			  AABB bbox;
			  pRE->mfGetBBox(bbox.min,bbox.max);
			  bbox.Move(vObjectPos);
			  bIsInRange = Overlap::Sphere_AABB(Sphere(snowVolParams.m_vWorldPos, snowVolParams.m_fRadius), bbox);
			  fObjectHeight = bbox.max.z;
		  }

		  // Only set if valid and within range and not underwater.
		  if ((CRenderer::CV_r_snow > 0) && (snowVolParams.m_fSnowAmount > 0.05f || snowVolParams.m_fFrostAmount > 0.05f || snowVolParams.m_fSurfaceFreezing > 0.05f)
			  && (snowVolParams.m_fRadius > 0.05f) && ( bIsTerrain || (bIsInRange && (fObjectHeight > gEnv->p3DEngine->GetWaterLevel(&vObjectPos) - 0.5f))))
		  {
			  SRenderObjData *const __restrict pOD = pObj->GetObjData(nThreadID);
			  IRenderNode *pRenderNode = (pOD && pOD->m_pInstance) ? (IRenderNode*) pOD->m_pInstance : 0;

			  // No render node = brush.
			  if(!pRenderNode && !(pObj->m_ObjFlags & (FOB_IN_DOORS | FOB_BENDED)) && (pObj->m_nVisAreaStencilRef <= 0))
				  sData[0].f[0] = 1; // Enabled
		  }
	  }
  }
  NO_INLINE void sCausticsSmoothSunDirection(UFloat4 *sData)
  {
    SCGParamsPF &PF = gRenDev->m_cEF.m_PF;
    Vec3 v(0.0f,0.0f,0.0f);
    I3DEngine *pEng = gEnv->p3DEngine;  

    // Caustics are done with projection from sun - ence they update too fast with regular
    // sun direction. Use a smooth sun direction update instead to workaround this
    if( PF.nCausticsFrameID != gRenDev->GetFrameID(false) )
    {
      PF.nCausticsFrameID = gRenDev->GetFrameID(false);
			Vec3 pRealtimeSunDirNormalized = pEng->GetRealtimeSunDirNormalized();

			const float fSnapDot = 0.98f; 
      float fDot = fabs(PF.vCausticsCurrSunDir.Dot(pRealtimeSunDirNormalized));
      if( fDot < fSnapDot )
        PF.vCausticsCurrSunDir = pRealtimeSunDirNormalized;   

      PF.vCausticsCurrSunDir += (pRealtimeSunDirNormalized - PF.vCausticsCurrSunDir) * 0.005f * gEnv->pTimer->GetFrameTime();
      PF.vCausticsCurrSunDir.Normalize(); 
    }

    v = PF.vCausticsCurrSunDir;

    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = 0;
  }

  void sHMAGradients(UFloat4 *sData)
  {
    SRenderPipeline& RESTRICT_REFERENCE rRP = gRenDev->m_RP;
    CRendElementBase *pRE = rRP.m_pRE;
    assert(pRE->mfGetType() == eDATA_Mesh);






    CRenderMesh* pRM  = ((CREMeshImpl*)pRE)->m_pRenderMesh;

    if (pRM)
    {
      AABB Box;
      pRM->GetBBox(Box.min,Box.max);
      CRenderObject *pObj = rRP.m_pCurObject;

      SRenderObjData *pOD = pObj->GetObjData(rRP.m_nProcessThreadID);
      assert(pOD);
      if (!pOD)
        return;

      const float RANGE	=	static_cast<float>((1<<2)-1)+0.5f;//0.5for rounding
      const unsigned int HMAIndex	=	pOD->m_HMAData;
      const float HMARange				=	pOD->m_fHMAData/RANGE;

      const float H0	=	static_cast<float>(HMAIndex&((1<<3)-1))*HMARange-RANGE*HMARange;
      const float H1	=	static_cast<float>((HMAIndex>>3)&((1<<3)-1))*HMARange-RANGE*HMARange;
      const float H2	=	static_cast<float>((HMAIndex>>6)&((1<<3)-1))*HMARange-RANGE*HMARange;
      const float H3	=	static_cast<float>((HMAIndex>>9)&((1<<3)-1))*HMARange-RANGE*HMARange;

      const float DeltaX	=	Box.max.x-Box.min.x;
      const float DeltaY	=	Box.max.y-Box.min.y;
      if(fabs(DeltaX)>FLT_EPSILON && fabs(DeltaY)>FLT_EPSILON)
      {
        sData[0].f[0] = (H0-H1)/DeltaX;
        sData[0].f[1] = (H2-H3)/DeltaY;
        sData[0].f[2] = ((H0+H1)*0.5f)/(DeltaX*DeltaX*0.25f);
        sData[0].f[3] = ((H2+H3)*0.5f)/(DeltaY*DeltaY*0.25f);
      }
      else
      {
        sData[0].f[0]=sData[0].f[1]=sData[0].f[2]=sData[0].f[3]=0.f;
      }
    }
  }

  NO_INLINE void sAlphaTest(UFloat4 *sData, const float dissolveRef)
  {
    SRenderPipeline& RESTRICT_REFERENCE rRP = gRenDev->m_RP;    
    sData[0].f[1] = rRP.m_pCurObject->m_ObjFlags & FOB_DISSOLVE_OUT ? 1.0f : -1.0f;
		sData[0].f[2] = 0;
    sData[0].f[3] = rRP.m_pShaderResources ? rRP.m_pShaderResources->m_AlphaRef : 0;

		// Use free component for SSDO
		if ((rRP.m_nPassGroupID != EFSLIST_TRANSP) && CRenderer::CV_r_ssdo)
			sData[0].f[2] = CRenderer::CV_r_ssdoAmount;

    // specific condition for hair zpass
    if ((rRP.m_pShader->m_Flags2 & EF2_HAIR) && !(rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN))
      sData[0].f[3] = 0.51f;

    sData[0].f[0] = dissolveRef*(1.0f/255.0f);
  }
  
  NO_INLINE void sDetailParams(UFloat4 *sData)
  {
		sData[0].f[2] = 0;
		sData[0].f[3] = CRenderer::CV_r_detaildistance;

    if (gRenDev->m_RP.m_pShaderResources)
    {
			if( SEfResTexture *pTex = gRenDev->m_RP.m_pShaderResources->GetTexture(EFTT_DETAIL_OVERLAY) )
			{
				sData[0].f[0] = pTex->GetTiling(0);
				sData[0].f[1] = pTex->GetTiling(1);

				if( !sData[0].f[0] ) sData[0].f[0] = 1.0f;
				if( !sData[0].f[1] ) sData[0].f[1] = 1.0f;
				return;
			}
    }

		sData[0].f[0] = sData[0].f[1] = 1.0f;
    
  }

  NO_INLINE void sFurParams(UFloat4 *sData)
  {
    if (gRenDev->m_RP.m_pShaderResources)
    {
      sData[0].f[0] = gRenDev->m_RP.m_pShaderResources->FurAmount(); 
      sData[0].f[1] = sData[0].f[0];
      sData[0].f[2] = sData[0].f[0];
      sData[0].f[3] = sData[0].f[0];
    }
    else
      sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = sData[0].f[3] = 0.f;
  }
  NO_INLINE void sVisionParams(UFloat4 *sData)
  {
    CRenderObject *pObj = gRenDev->m_RP.m_pCurObject;
		SRenderObjData *pOD = pObj->GetObjData( gRenDev->m_RP.m_nProcessThreadID );
		if( pOD )
    {
		  float fRecip = (1.0f / 255.0f);
			if(gRenDev->m_nThermalVisionMode && CRenderer::CV_r_cloakRenderInThermalVision &&  gRenDev->m_RP.m_pCurObject->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK)
			fRecip *= CRenderer::CV_r_cloakHeatScale;
			
			uint32 nParams(pOD->m_nHUDSilhouetteParams);
			if( gRenDev->m_RP.m_PersFlags2 & RBPF2_THERMAL_RENDERMODE_PASS )
			{
				nParams = pOD->m_nVisionParams;
				fRecip *= (float)pOD->m_nVisionScale;
			}

			sData[0].f[0] = float((nParams&0xff000000)>>24) * fRecip;
			sData[0].f[1] = float((nParams&0x00ff0000)>>16) * fRecip;
			sData[0].f[2] = float((nParams&0x0000ff00)>>8 ) * fRecip;
			sData[0].f[3] = float((nParams&0x000000ff) ) * fRecip;
      
		  if( CRenderer::CV_r_customvisions == 2 && !gRenDev->IsCustomRenderModeEnabled(eRMF_MASK)) 
			  sData[0].f[3] = gEnv->pTimer->GetCurrTime() + ((float)(2 * pObj->m_Id) / 32768.0f );
    }
    else
    {
      sData[0].f[0] = 0;
      sData[0].f[1] = 0;
      sData[0].f[2] = 0;
      sData[0].f[3] = 0;
    }
  }

	NO_INLINE void sVisionMtlParams(UFloat4 *sData)
	{
		Vec3 vCameraPos = gRenDev->GetRCamera().Orig;
		Vec3 vObjectPos = gRenDev->m_RP.m_pCurObject->GetTranslation();
		const float fRecipThermalViewDist = 1.0f / (CRenderer::CV_r_ThermalVisionViewDistance*CRenderer::CV_r_ThermalVisionViewDistance);

		SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;
		float heatAmount = 0.0f;
		if (gRenDev->m_nThermalVisionMode && pRes)
		{
				const int nThreadID = gRenDev->m_RP.m_nProcessThreadID;
				SRenderObjData *pOD = gRenDev->m_RP.m_pCurObject->GetObjData(nThreadID);
				if (!pOD || !(pOD->m_nCustomFlags&COB_IGNORE_HEAT_AMOUNT))
				{
					heatAmount=pRes->HeatAmount();

					if (gRenDev->m_RP.m_pCurObject->m_nMaterialLayers & MTL_LAYER_BLEND_CLOAK)
					{
						if (CRenderer::CV_r_cloakRenderInThermalVision)
						{
							heatAmount *= CRenderer::CV_r_cloakHeatScale;
						}
						else
						{
							heatAmount = 0.0f;
						}
					}
				}
		}
		sData[0].f[0] = heatAmount;
		sData[0].f[0] *= 1.0f - min(1.0f,  vObjectPos.GetSquaredDistance(vCameraPos) * fRecipThermalViewDist  );

		//Cloaked objects should flicker in thermal vision
		if(gRenDev->m_RP.m_nPassGroupID == EFSLIST_TRANSP && gRenDev->m_RP.m_pCurObject->m_ObjFlags & FOB_REQUIRES_RESOLVE)
		{
			static void *pPrevNode = NULL;
			static int prevFrame = 0;
			static float fScale = 1.0f;

			if( CRenderer::CV_r_ThermalVisionViewCloakFlickerMinIntensity == CRenderer::CV_r_ThermalVisionViewCloakFlickerMaxIntensity )
			{
				//Simple scaling
				fScale = CRenderer::CV_r_ThermalVisionViewCloakFlickerMinIntensity;
			}
			else if( ( pPrevNode != gRenDev->m_RP.m_pCurObject->m_pRenderNode ) || ( prevFrame != gRenDev->GetFrameID(true) ) )
			{
				uint32 sineKey = (uint32)gRenDev->m_RP.m_pCurObject->m_pRenderNode + gRenDev->GetFrameID(true);
				fScale = (float)(
									clamp_tpl( sin( ( double )( sineKey / CRenderer::CV_r_ThermalVisionViewCloakFrequencyPrimary ) ), 0.0, 1.0 ) *
									clamp_tpl( sin( ( double )( sineKey / CRenderer::CV_r_ThermalVisionViewCloakFrequencySecondary ) ), 0.0, 1.0 )
									);
				fScale = CRenderer::CV_r_ThermalVisionViewCloakFlickerMinIntensity + ( ( CRenderer::CV_r_ThermalVisionViewCloakFlickerMaxIntensity - CRenderer::CV_r_ThermalVisionViewCloakFlickerMinIntensity ) * fScale ); 
			}
			sData[0].f[0] *= fScale;

			//Cache parameters for use in the next call, to provide a consistent value for an individual character
			pPrevNode = gRenDev->m_RP.m_pCurObject->m_pRenderNode;
			prevFrame = gRenDev->GetFrameID(true);
		}

		sData[0].f[1] = sData[0].f[2] = sData[0].f[2] = 0.0f;
	}

	NO_INLINE void sEffectLayerParams(UFloat4 *sData)
	{
		CRenderObject *pObj = gRenDev->m_RP.m_pCurObject;
		if( !CRenderer::CV_r_DebugLayerEffect )
		{
			SRenderObjData *pOD = pObj->GetObjData( gRenDev->m_RP.m_nProcessThreadID );
			if( pOD )
			{
				float fRecip = (1.0f / 255.0f);
				sData[0].f[0] = float((pOD->m_pLayerEffectParams&0xff000000)>>24) * fRecip;
				sData[0].f[1] = float((pOD->m_pLayerEffectParams&0x00ff0000)>>16) * fRecip;
				sData[0].f[2] = float((pOD->m_pLayerEffectParams&0x0000ff00)>>8 ) * fRecip;
				sData[0].f[3] = float((pOD->m_pLayerEffectParams&0x000000ff) ) * fRecip;
			}
			else
				sZeroLine(sData);
		}
		else
		{
			
			const uint32 nDebugModesCount = 4;
			static const Vec4 pDebugModes[ nDebugModesCount ]=
			{
				Vec4( 1, 0, 0, 0),
				Vec4( 0, 1, 0, 0),
				Vec4( 0, 0, 1, 0),
				Vec4( 0, 0, 0, 1),
			};
			
			uint32 nCurrDebugMode = min( nDebugModesCount, (uint32)CRenderer::CV_r_DebugLayerEffect) - 1;

			sData[0].f[0] = pDebugModes[ nCurrDebugMode ].x;
			sData[0].f[1] = pDebugModes[ nCurrDebugMode ].y;
			sData[0].f[2] = pDebugModes[ nCurrDebugMode ].z;
			sData[0].f[3] = pDebugModes[ nCurrDebugMode ].w;
		}

	}


  NO_INLINE void sMaterialLayersParams(UFloat4 *sData)
  {
    CRenderObject *pObj = gRenDev->m_RP.m_pCurObject;
    sData[0].f[0] = ((pObj->m_nMaterialLayers&MTL_LAYER_BLEND_DYNAMICFROZEN))/255.0f;
    sData[0].f[1] = ((pObj->m_nMaterialLayers&MTL_LAYER_BLEND_WET)>>16)/254.0f; // account for missing low end bit
    // Apply attenuation
    sData[0].f[1] *= 1.0f - min(1.0f, pObj->m_fDistance / CRenderer::CV_r_rain_maxviewdist);

		sData[0].f[2] = (pObj->m_ObjFlags & FOB_DISSOLVE)?(1.f/255.f)*pObj->m_DissolveRef:((pObj->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK)>>8)/255.0f;

    sData[0].f[3] = 0;//(pObj->m_ObjFlags & FOB_MTLLAYERS_OBJSPACE)? 1.0f : 0.0f;
  }

  NO_INLINE void sLightningColSize(UFloat4 *sData)
  {
    Vec3 v;
    gEnv->p3DEngine->GetGlobalParameter(E3DPARAM_SKY_HIGHLIGHT_COLOR, v);
    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;

    gEnv->p3DEngine->GetGlobalParameter(E3DPARAM_SKY_HIGHLIGHT_SIZE, v);
    sData[0].f[3] = v.x * 0.01f;			
  }

  NO_INLINE void sTexelsPerMeterInfo(UFloat4 *sData)
  {
    sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = sData[0].f[3] = 0;
    SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;
    if (pRes && pRes->m_Textures[EFTT_DIFFUSE])
    {
      CTexture* pTexture(pRes->m_Textures[EFTT_DIFFUSE]->m_Sampler.m_pTex);
      if (pTexture)
      {
        int texWidth(pTexture->GetWidth());
        int texHeight(pTexture->GetHeight());
        float ratio = 0.5f / CRenderer::CV_r_TexelsPerMeter;
        sData[0].f[0] = (float) texWidth * ratio;
        sData[0].f[1] = (float) texHeight * ratio;
      }
    }
  }

  NO_INLINE void sOceanMat(UFloat4 *sData)
  {
    const CRenderCamera& cam(gRenDev->GetRCamera());

    Matrix44A viewMat;				
    viewMat.m00 = cam.X.x; viewMat.m01 = cam.Y.x; viewMat.m02 = cam.Z.x; viewMat.m03 = 0;					
    viewMat.m10 = cam.X.y; viewMat.m11 = cam.Y.y; viewMat.m12 = cam.Z.y; viewMat.m13 = 0;
    viewMat.m20 = cam.X.z; viewMat.m21 = cam.Y.z; viewMat.m22 = cam.Z.z; viewMat.m23 = 0;
    viewMat.m30 = 0; viewMat.m31 = 0; viewMat.m32 = 0; viewMat.m33 = 1;
		Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
    pMat->Multiply(viewMat, *gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_matProj->GetTop());
    pMat->Transpose(*pMat);
  }

  NO_INLINE void sResInfoDiffuse(UFloat4 *sData)
  {
    sIdentityLine(sData);
    SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;
    if (pRes && pRes->m_Textures[EFTT_DIFFUSE])
    {
      ITexture* pTexture(pRes->m_Textures[EFTT_DIFFUSE]->m_Sampler.m_pTex);
      if (pTexture)
      {
        int texWidth(pTexture->GetWidth());
        int texHeight(pTexture->GetHeight());
        sData[0].f[0] = (float) texWidth;
        sData[0].f[1] = (float) texHeight;
        if (texWidth && texHeight)
        {
          sData[0].f[2] = 1.0f / (float) texWidth;
          sData[0].f[3] = 1.0f / (float) texHeight;
        }
      }
    }
  }

  NO_INLINE void sTexelDensityParam(UFloat4 *sData)
  {
    sIdentityLine(sData);

		SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;

		if (pRes && pRes->m_Textures[EFTT_DIFFUSE])
		{
			CRenderChunk *pRenderChunk = NULL;
			int texWidth = 512;
			int texHeight = 512;
			int mipLevel = 0;

			CRendElementBase *pRE = gRenDev->m_RP.m_pRE;

			if (pRE)
			{
				pRenderChunk = pRE->mfGetMatInfo();
			}

			CRenderObject *pCurObject = gRenDev->m_RP.m_pCurObject;

			if (pRenderChunk && pCurObject)
			{
				float weight = 1.0f;

				if (pRenderChunk->m_texelAreaDensity > 0.0f)
				{
					float scale = 1.0f;

					IRenderNode *pRenderNode = (IRenderNode *)pCurObject->m_pRenderNode;

					if (pRenderNode && pRenderNode != (void *)0xffffffff && pRenderNode != (void *)-1 && pRenderNode->GetRenderNodeType() == eERType_Brush)
					{
						scale = ((IBrush *)pRenderNode)->GetMatrix().GetColumn0().GetLength();
					}

					float distance = pCurObject->m_fDistance * TANGENT30_2 / scale;
					int screenHeight = gRenDev->GetHeight();

					weight = pRenderChunk->m_texelAreaDensity * distance * distance * texWidth * texHeight * pRes->m_Textures[EFTT_DIFFUSE]->GetTiling(0) * pRes->m_Textures[EFTT_DIFFUSE]->GetTiling(1) / (screenHeight * screenHeight);
				}

				mipLevel = fastround_positive(0.5f * logf(max(weight,1.0f)) / LN2);
			}

			texWidth /= (1 << mipLevel);
			texHeight /= (1 << mipLevel);

			if (texWidth == 0)
				texWidth = 1;
			if (texHeight == 0)
				texHeight = 1;

			sData[0].f[0] = (float) texWidth;
			sData[0].f[1] = (float) texHeight;
			sData[0].f[2] = 1.0f / (float) texWidth;
			sData[0].f[3] = 1.0f / (float) texHeight;
		}
  }

  NO_INLINE void sTexelDensityColor(UFloat4 *sData)
  {
    sOneLine(sData);

		SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;

		if (pRes && pRes->m_Textures[EFTT_DIFFUSE])
		{
			if (CRenderer::CV_e_DebugTexelDensity == 2 || gcpRendD3D->CV_e_DebugTexelDensity == 4)
			{
				CRenderChunk *pRenderChunk = NULL;
				int texWidth = 512;
				int texHeight = 512;
				int mipLevel = 0;

				CRendElementBase *pRE = gRenDev->m_RP.m_pRE;

				if (pRE)
				{
					pRenderChunk = pRE->mfGetMatInfo();
				}

				CRenderObject *pCurObject = gRenDev->m_RP.m_pCurObject;

				if (pRenderChunk && pCurObject)
				{
					float weight = 1.0f;

					if (pRenderChunk->m_texelAreaDensity > 0.0f)
					{
						float scale = 1.0f;

						IRenderNode *pRenderNode = (IRenderNode *)pCurObject->m_pRenderNode;

						if (pRenderNode && pRenderNode != (void *)0xffffffff && pRenderNode != (void *)-1 && pRenderNode->GetRenderNodeType() == eERType_Brush)
						{
							scale = ((IBrush *)pRenderNode)->GetMatrix().GetColumn0().GetLength();
						}

						float distance = pCurObject->m_fDistance * TANGENT30_2 / scale;
						int screenHeight = gRenDev->GetHeight();

						weight = pRenderChunk->m_texelAreaDensity * distance * distance * texWidth * texHeight * pRes->m_Textures[EFTT_DIFFUSE]->GetTiling(0) * pRes->m_Textures[EFTT_DIFFUSE]->GetTiling(1) / (screenHeight * screenHeight);
					}

					mipLevel = fastround_positive(0.5f * logf(max(weight,1.0f)) / LN2);
				}

				switch (mipLevel)
				{
					case 0:
						sData[0].f[0] = 1.0f; sData[0].f[1] = 1.0f; sData[0].f[2] = 1.0f; break;
					case 1:
						sData[0].f[0] = 0.0f; sData[0].f[1] = 0.0f; sData[0].f[2] = 1.0f; break;
					case 2:
						sData[0].f[0] = 0.0f; sData[0].f[1] = 1.0f; sData[0].f[2] = 0.0f; break;
					case 3:
						sData[0].f[0] = 0.0f; sData[0].f[1] = 1.0f; sData[0].f[2] = 1.0f; break;
					case 4:
						sData[0].f[0] = 1.0f; sData[0].f[1] = 0.0f; sData[0].f[2] = 0.0f; break;
					case 5:
						sData[0].f[0] = 1.0f; sData[0].f[1] = 0.0f; sData[0].f[2] = 1.0f; break;
					default:
						sData[0].f[0] = 1.0f; sData[0].f[1] = 1.0f; sData[0].f[2] = 0.0f; break;
				}
			}
			else
			{
				sData[0].f[0] = 1.0f; sData[0].f[1] = 1.0f; sData[0].f[2] = 1.0f;
			}
		}
	}

  NO_INLINE void sResInfoBump(UFloat4 *sData)
  {
    //PS3HACK
    sIdentityLine(sData);
#if !defined(PS3)
    SRenderShaderResources *pRes = gRenDev->m_RP.m_pShaderResources;
    if (pRes && pRes->m_Textures[EFTT_BUMP])
    {
      ITexture* pTexture(pRes->m_Textures[EFTT_BUMP]->m_Sampler.m_pTex);
      if (pTexture)
      {
        int texWidth(pTexture->GetWidth());
        int texHeight(pTexture->GetHeight());
        sData[0].f[0] = (float) texWidth;
        sData[0].f[1] = (float) texHeight;
        sData[0].f[2] = 1.0f / (float) max(1, texWidth);
        sData[0].f[3] = 1.0f / (float) max(1, texHeight);
      }
    }
#endif
  }

  NO_INLINE void sNumInstructions(UFloat4 *sData)
  {
    sData[0].f[0] = gRenDev->m_RP.m_NumShaderInstructions / CRenderer::CV_r_measureoverdrawscale / 256.0f;
  }

  NO_INLINE void sSkyColor(UFloat4 *sData)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SCGParamsPF &PF = r->m_cEF.m_PF;
    I3DEngine *pEng = gEnv->p3DEngine;
    Vec3 v = pEng->GetSkyColor();
    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = CRenderer::CV_r_useSRGB != 0; // only way of doing test without adding more permutations;

    if (CRenderer::CV_r_PostProcess && CRenderer::CV_r_NightVision == 1)
    {
      // If nightvision active, brighten up ambient
      if (PF.bPE_NVActive)
      {
        sData[0].f[0] += 0.25f;//0.75f;
        sData[0].f[1] += 0.25f;//0.75f;
        sData[0].f[2] += 0.25f;//0.75f;  
      }
    }
  }

  NO_INLINE void sAmbient(UFloat4 *sData, SRenderPipeline& rRP, const SInstanceInfo &instInfo)
  {
    sData[0].f[0] = instInfo.m_AmbColor[0];
    sData[0].f[1] = instInfo.m_AmbColor[1]; 
    sData[0].f[2] = instInfo.m_AmbColor[2];  
    sData[0].f[3] = instInfo.m_AmbColor[3];

    if (SRenderShaderResources *pRes=rRP.m_pShaderResources)
    {
      sData[0].f[0] += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][0];
      sData[0].f[1] += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][1];
      sData[0].f[2] += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][2];
      if (pRes->m_ResFlags & MTL_FLAG_ADDITIVE)
      {
        sData[0].f[0] *= rRP.m_fCurOpacity;
        sData[0].f[1] *= rRP.m_fCurOpacity;
        sData[0].f[2] *= rRP.m_fCurOpacity;
      }
    }
  }
  NO_INLINE void sAmbientOpacity(UFloat4 *sData, const SInstanceInfo &instInfo)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SCGParamsPF & RESTRICT_REFERENCE PF = r->m_cEF.m_PF;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    CRenderObject *const __restrict pObj = rRP.m_pCurObject;
		
		float op = rRP.m_fCurOpacity;
		float a0 = instInfo.m_AmbColor[0];
		float a1 = instInfo.m_AmbColor[1];
		float a2 = instInfo.m_AmbColor[2];
		float a3 = instInfo.m_AmbColor[3];
		float opal = op * pObj->m_fAlpha;
    float s0 = a0;
    float s1 = a1; 
    float s2 = a2;
    float s3 = opal;// object opacity  

    if (pObj->m_nMaterialLayers)
      s3 *= sGetMaterialLayersOpacity(sData, r);

    if (SRenderShaderResources *pRes=rRP.m_pShaderResources)
    {
      if (rRP.m_nShaderQuality == eSQ_Low)
      {
				float c0 = pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][0];
				float c1 = pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][1];
				float c2 = pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][2];

        s0 *= c0;
        s1 *= c1;
        s2 *= c2;
      }
      s0 += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][0];
      s1 += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][1];
      s2 += pRes->m_Constants[eHWSC_Pixel][PS_EMISSIVE_COL][2];

      if (pRes->m_ResFlags & MTL_FLAG_ADDITIVE)
      {
        s0 *= rRP.m_fCurOpacity;
        s1 *= rRP.m_fCurOpacity;
        s2 *= rRP.m_fCurOpacity;
      }

      if (CRenderer::CV_r_PostProcess && CRenderer::CV_r_NightVision == 1)
      {
        // If nightvision active, brighten up ambient
        //   float fOffset = (CRenderer::CV_r_HDRRendering) ? 1.25f : 0.25;
        if (PF.bPE_NVActive)
        { 
          s0 += 0.25f;//fOffset;
          s1 += 0.25f;//fOffset;
          s2 += 0.25f;//fOffset;  
        }
      }
    }

		if( !(rRP.m_PersFlags2 & RBPF2_POST_3D_RENDERER_PASS) ) 
		{
			if( ! (pObj->m_nMaterialLayers&MTL_LAYER_BLEND_CLOAK) )
			{
				sData[0].f[0] = s0;
				sData[0].f[1] = s1;
				sData[0].f[2] = s2;
			}
			else
			{
				// Apply minimum ambient to cloaking objects - this avoids the cloak transition going black
				// if there's no lights on the object
				float minCloakAmbient = CRenderer::CV_r_cloakMinAmbientOutdoors;

				// Determine if object is affected by outdoor lighting
				if(rRP.m_ObjFlags & FOB_IN_DOORS)
				{
					// Object is indoors, so use indoors min ambient
					minCloakAmbient = CRenderer::CV_r_cloakMinAmbientIndoors;
				}

				sData[0].f[0] = max(minCloakAmbient,s0);
				sData[0].f[1] = max(minCloakAmbient,s1);
				sData[0].f[2] = max(minCloakAmbient,s2);
			}
			sData[0].f[3] = s3;
		}
		else
		{
			Vec4 ambient = gRenDev->m_cEF.m_PF.post3DRendererAmbient;
			sData[0].f[0] = ambient.x;
			sData[0].f[1] = ambient.y;
			sData[0].f[2] = ambient.z;
			sData[0].f[3] = ambient.w;
		}
  }

  NO_INLINE void sObjectAmbColComp(UFloat4 *sData, const SInstanceInfo &instInfo, const float fRenderQuality)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SCGParamsPF &PF = r->m_cEF.m_PF;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    CRenderObject *pObj = rRP.m_pCurObject;
    sData[0].f[0] = instInfo.m_AmbColor[3];
    sData[0].f[1] = /*instInfo.m_AmbColor[3] * */rRP.m_fCurOpacity * pObj->m_fAlpha;

    if (pObj->m_nMaterialLayers)
      sData[0].f[1] *= sGetMaterialLayersOpacity( sData, r );

    sData[0].f[2] = 0.f;
    sData[0].f[3] = fRenderQuality * (1.0f / 65535.0f);
  }

  NO_INLINE void sMatEmissiveColor(UFloat4 *sData, const SCGParam *ParamBind, EHWShaderClass eSH)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SCGParamsPF &PF = r->m_cEF.m_PF;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    if (SRenderShaderResources *pRes=r->m_RP.m_pShaderResources)
    {
  #ifdef DIRECT3D10
      assert(0);
  #else
      Vec4 *pConsts = (Vec4 *)&pRes->m_Constants[eSH][0];
      pConsts -= FIRST_REG_PM[eSH];
      int i = ParamBind->m_dwBind;
      sData[0].f[0] = pConsts[i][0];
      sData[0].f[1] = pConsts[i][1];
      sData[0].f[2] = pConsts[i][2];
      sData[0].f[3] = pConsts[i][3];

      if (pRes->m_ResFlags & MTL_FLAG_ADDITIVE)
      {
        sData[0].f[0] *= rRP.m_fCurOpacity;
        sData[0].f[1] *= rRP.m_fCurOpacity;
        sData[0].f[2] *= rRP.m_fCurOpacity;
      }

      if (CRenderer::CV_r_PostProcess && CRenderer::CV_r_NightVision == 1)
      {
        // If nightvision active, brighten up ambient
        if (PF.bPE_NVActive)
        { 
          sData[0].f[0] += 0.25f;//fOffset;
          sData[0].f[1] += 0.25f;//fOffset;
          sData[0].f[2] += 0.25f;//fOffset;  
        }
      }
  #endif
    }
    else
    {
      assert(0);
    }
  }

  NO_INLINE void sTweakable(UFloat4 *sData, const SCGParam *ParamBind, EHWShaderClass eSH)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

  // excessive safety check
  // m_pShaderResources should never be NULL (unless there is some error in a system design)
  // so NULL check could be skipped for RELEASE builds
  if (SRenderShaderResources *pRes=rRP.m_pShaderResources)
  {
# ifdef DIRECT3D10
    assert(0);
# else
#ifndef _RELEASE
      if (eSH < 2)
#endif
      {
        Vec4 *pConsts = (Vec4 *)&pRes->m_Constants[eSH][0];
        assert(ParamBind->m_dwBind-FIRST_REG_PM[eSH] < (short)rRP.m_pShaderResources->m_Constants[eSH].size());
        SRenderObjData *pD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
        if (pD && pD->m_Constants.size())
          pConsts = &pD->m_Constants[0];
        pConsts -= FIRST_REG_PM[eSH];
        int i = ParamBind->m_dwBind;
        sData[0].f[0] = pConsts[i][0];
        sData[0].f[1] = pConsts[i][1];
        sData[0].f[2] = pConsts[i][2];
        sData[0].f[3] = pConsts[i][3];

        if( ParamBind->m_eCGParamType == ECGP_PM_MatDiffuseColor )
        {
          // Apply shading to custom environment maps (and skip for nearest cubemap feature since these are based on real scene don't need shading) 
          const float fShadeEnvCM = (pRes->m_Textures[EFTT_ENV] && pRes->m_Textures[EFTT_ENV]->m_Sampler.m_eTexType == eTT_NearestCube)? 0.0f : 1.0f;
          sData[0].f[3] = fShadeEnvCM;
        }

        if (pRes->m_ResFlags & MTL_FLAG_ADDITIVE)
        {
          sData[0].f[0] *= rRP.m_fCurOpacity;
          sData[0].f[1] *= rRP.m_fCurOpacity;
          sData[0].f[2] *= rRP.m_fCurOpacity;
        }
      }
# endif
  }
  else
  {
    assert(0);
  }
  }

  NO_INLINE void sTextureTileSize(UFloat4 *sData, SRenderPipeline& rRP)
  {
    SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
    if (pOD)
    {
      float* pTexTileSize = (float*)&pOD->m_fTempVars[0];
      sData[0].f[0] = pTexTileSize[0];
      sData[0].f[1] = pTexTileSize[1];
      sData[0].f[2] = pTexTileSize[2];
      sData[0].f[3] = pTexTileSize[3];
    }
  }

	NO_INLINE void sMotionBlurInfo(UFloat4 *sData, SRenderPipeline& rRP)
	{
		SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
		if (pOD)
		{
			float* pMBInfo = (float*)&pOD->m_fTempVars[4];
			sData[0].f[0] = pMBInfo[0];
			sData[0].f[1] = pMBInfo[1];
			sData[0].f[2] = pMBInfo[2];
			sData[0].f[3] = pMBInfo[3];
		}
	}

	NO_INLINE void sParticleParams(UFloat4 *sData, SRenderPipeline& rRP)
	{
		SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
		if (pOD)
		{
			sData[0].f[0] = pOD->m_pParticleParams->fAlpha.GetMaxValue();							// Alpha scale
			sData[0].f[1] = pOD->m_pParticleParams->fDiffuseLighting;
			sData[0].f[2] = pOD->m_pParticleParams->fDiffuseBacklighting;
			sData[0].f[3] = pOD->m_pParticleParams->eFacing == ParticleFacing_Camera ? 1.f : 0.f;	// Curved normals
		}
	}

	NO_INLINE void sSunDirection(UFloat4 *sData)
  {
    I3DEngine *pEng = gEnv->p3DEngine;  
    Vec3 v = pEng->GetSunDirNormalized();
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    if((rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_MAKESPRITE) && (SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID]==2) && rRP.m_DLights[rRP.m_nProcessThreadID][1].Num())
    {
      v = rRP.m_DLights[rRP.m_nProcessThreadID][1][0].m_Origin;
      v.Normalize();
    }
    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = r->m_fAdaptedSceneScale;
  }

  NO_INLINE void sAvgFogVolumeContrib(UFloat4 *sData)
  {
    CD3D9Renderer *const __restrict r = gcpRendD3D;
		SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

		if( ! (rRP.m_PersFlags2 & RBPF2_POST_3D_RENDERER_PASS) )
		{
			SCGParamsPF &PF = r->m_cEF.m_PF;
			CRenderObject *pObj = rRP.m_pCurObject;
			SRenderObjData *pOD = r->FX_GetObjData(pObj);
			if (!pOD || pOD->m_FogVolumeContribIdx[rRP.m_nProcessThreadID] == (uint16)-1) 
				return;

			ColorF contrib;
			r->GetFogVolumeContribution(pOD->m_FogVolumeContribIdx[rRP.m_nProcessThreadID], contrib);
			// Pre-multiply alpha (saves 1 instruction in pixel shader)
			if (rRP.m_bFirstPass)
			{
				sData[0].f[0] = contrib.r * (1 - contrib.a);   
				sData[0].f[1] = contrib.g * (1 - contrib.a);
				sData[0].f[2] = contrib.b * (1 - contrib.a);
			}
			else
			{
				sData[0].f[0] = 0.0f;
				sData[0].f[1] = 0.0f;
				sData[0].f[2] = 0.0f;
			}
			sData[0].f[3] = contrib.a;
		}
		else
		{
			// RBPF2_POST_3D_RENDERER_PASS
			sData[0].f[0] = 0.0f;
			sData[0].f[1] = 0.0f;
			sData[0].f[2] = 0.0f;
			sData[0].f[3] = 1.0f;
		}
  }

  NO_INLINE void sDiffuseMulti(UFloat4 *sData, const SInstanceInfo &instInfo)
  {
    SRenderLight *pDL;
    SLightPass *pLP;
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    pLP = &rRP.m_LPasses[rRP.m_nCurLightPass];
    for (uint32 i=0; i<pLP->nLights; i++)
    {
      pDL = pLP->pLights[i];
      sData[i].f[0] = pDL->m_Color[0];
      sData[i].f[1] = pDL->m_Color[1];
      sData[i].f[2] = pDL->m_Color[2];
      sData[i].f[3] = rRP.m_fCurOpacity * rRP.m_pCurObject->m_fAlpha * instInfo.m_AmbColor[3];

      if (rRP.m_pCurObject->m_nMaterialLayers)
        sData[i].f[3] *= sGetMaterialLayersOpacity(sData, r);

      if (SRenderShaderResources *pRes=rRP.m_pShaderResources)
      {
        if (pRes->m_ResFlags & MTL_FLAG_ADDITIVE)
        {
          sData[i].f[0] *= rRP.m_fCurOpacity;
          sData[i].f[1] *= rRP.m_fCurOpacity;
          sData[i].f[2] *= rRP.m_fCurOpacity;
        }
      }
    }
  }

  NO_INLINE void sShadowMask(UFloat4 *sData)
  {
    SRenderLight *pDL;
    SLightPass *pLP;
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    pLP = &rRP.m_LPasses[rRP.m_nCurLightPass];
    for (uint32 i=0; i<pLP->nLights; i++)
    {
      pDL = pLP->pLights[i];
			sData[i].f[0] = (pDL->m_ShadowChanMask & (1<<0))?1.0f:0.0f;
      sData[i].f[1] = (pDL->m_ShadowChanMask & (1<<1))?1.0f:0.0f;
      sData[i].f[2] = (pDL->m_ShadowChanMask & (1<<2))?1.0f:0.0f;
      sData[i].f[3] = (pDL->m_ShadowChanMask & (1<<3))?1.0f:0.0f;
    }
  }

	NO_INLINE void sDepthFactor(UFloat4 *sData, CD3D9Renderer *r)
	{
		const CRenderCamera& rc = r->GetRCamera();
		float zn = rc.Near;
		float zf = rc.Far;
		//sData[0].f[3] = -(zf/(zf-zn));
		sData[0].f[3] = 0.0f;

		sData[0].f[0] = 255.0/256.0;
		sData[0].f[1] = 255.0/65536.0;
		sData[0].f[2] = 255.0/16777216.0;
	}
	NO_INLINE void sNearFarDist(UFloat4 *sData, CD3D9Renderer *r)
	{
		const CRenderCamera& rc = r->GetRCamera();
		I3DEngine *pEng = gEnv->p3DEngine;
		sData[0].f[0] = rc.Near;
		sData[0].f[1] = rc.Far;
		// NOTE : v[2] is used to put the weapon's depth range into correct relation to the whole scene
		// when generating the depth texture in the z pass (_RT_NEAREST)
		sData[0].f[2] = rc.Far / pEng->GetMaxViewDistance();
		sData[0].f[3] = 1.0f / rc.Far;
	}

  NO_INLINE void sGetTempData(UFloat4 *sData, CD3D9Renderer *r, const SCGParam *ParamBind)
  {
    sData[0].f[0] = r->m_cEF.m_TempVecs[ParamBind->m_nID].x;
    sData[0].f[1] = r->m_cEF.m_TempVecs[ParamBind->m_nID].y;
    sData[0].f[2] = r->m_cEF.m_TempVecs[ParamBind->m_nID].z;
    sData[0].f[3] = r->m_cEF.m_TempVecs[ParamBind->m_nID].w;
  }

  NO_INLINE void sCameraFront(UFloat4 *sData, CD3D9Renderer *r)
  {
    Vec3 v = r->GetRCamera().Z;
    v.Normalize();

    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = 0;
  }
  NO_INLINE void sCameraRight(UFloat4 *sData, CD3D9Renderer *r)
  {
    Vec3 v = r->GetRCamera().X;
    v.Normalize();

    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = 0;
  }
  NO_INLINE void sCameraUp(UFloat4 *sData, CD3D9Renderer *r)
  {
    Vec3 v = r->GetRCamera().Y;
    v.Normalize();

    sData[0].f[0] = v.x;
    sData[0].f[1] = v.y;
    sData[0].f[2] = v.z;
    sData[0].f[3] = 0;
  }

  NO_INLINE void sRTRect(UFloat4 *sData, CD3D9Renderer *r)
  {
    sData[0].f[0] = r->m_cEF.m_RTRect.x;
    sData[0].f[1] = r->m_cEF.m_RTRect.y;
    sData[0].f[2] = r->m_cEF.m_RTRect.z;
    sData[0].f[3] = r->m_cEF.m_RTRect.w;
  }

#ifndef EXCLUDE_SCALEFORM_SDK
  NO_INLINE void sSFCompMat(UFloat4 *sData, CD3D9Renderer *r)
  {
    const SSF_GlobalDrawParams* pParams(r->SF_GetGlobalDrawParams());
    assert(pParams);
    if (pParams)
    {
      Matrix44A& matComposite((Matrix44A&)sData[0].f[0]);
      matComposite = *pParams->pTransMat;
    }
  }
  NO_INLINE void sSFTexGenMat0(UFloat4 *sData, CD3D9Renderer *r)
  {
    const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
    assert(p);
    if (p)
    {
      const Matrix34A& mat(p->texture[0].texGenMat);
      sData[0].f[0] = mat.m00;
      sData[0].f[1] = mat.m01;
      sData[0].f[2] = mat.m02;
      sData[0].f[3] = mat.m03;

      sData[1].f[0] = mat.m10;
      sData[1].f[1] = mat.m11;
      sData[1].f[2] = mat.m12;
      sData[1].f[3] = mat.m13;
    }
  }
  NO_INLINE void sSFTexGenMat1(UFloat4 *sData, CD3D9Renderer *r)
  {
    const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
    assert(p);
    if (p)
    {
      const Matrix34A& mat(p->texture[1].texGenMat);
      sData[0].f[0] = mat.m00;
      sData[0].f[1] = mat.m01;
      sData[0].f[2] = mat.m02;
      sData[0].f[3] = mat.m03;

      sData[1].f[0] = mat.m10;
      sData[1].f[1] = mat.m11;
      sData[1].f[2] = mat.m12;
      sData[1].f[3] = mat.m13;
    }
  }
  NO_INLINE void sSFBitmapColorTransform(UFloat4 *sData, CD3D9Renderer *r)
  {
    const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
    assert(p);
    if (p)
    {
      const ColorF& col1st(p->colTransform1st);
      sData[0].f[0] = col1st.r;
      sData[0].f[1] = col1st.g;
      sData[0].f[2] = col1st.b;
      sData[0].f[3] = col1st.a;

      const ColorF& col2nd(p->colTransform2nd);
      sData[1].f[0] = col2nd.r;
      sData[1].f[1] = col2nd.g;
      sData[1].f[2] = col2nd.b;
      sData[1].f[3] = col2nd.a;
    }
  }
	NO_INLINE void sSFColorTransformMatrix(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			const ColorF* colMat(p->colTransformMat);
			sData[0].f[0] = colMat[0].r;
			sData[0].f[1] = colMat[1].r;
			sData[0].f[2] = colMat[2].r;
			sData[0].f[3] = colMat[3].r;

			sData[1].f[0] = colMat[0].g;
			sData[1].f[1] = colMat[1].g;
			sData[1].f[2] = colMat[2].g;
			sData[1].f[3] = colMat[3].g;

			sData[2].f[0] = colMat[0].b;
			sData[2].f[1] = colMat[1].b;
			sData[2].f[2] = colMat[2].b;
			sData[2].f[3] = colMat[3].b;

			sData[3].f[0] = colMat[0].a;
			sData[3].f[1] = colMat[1].a;
			sData[3].f[2] = colMat[2].a;
			sData[3].f[3] = colMat[3].a;
		}
	}
  NO_INLINE void sSFStereoVideoFrameSelect(UFloat4 *sData, CD3D9Renderer *r)
  {
    const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
    assert(p);
    if (p)
    {
      const ColorF& col1st(p->colTransform1st);
      sData[0].f[0] = p->texGenYUVAStereo.x;
      sData[0].f[1] = p->texGenYUVAStereo.y;
      sData[0].f[2] = 0;
      sData[0].f[3] = 0;
    }
  }
	NO_INLINE void sSFPremultipliedAlpha(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->premultipliedAlpha ? 1.f : 0.f;
			sData[0].f[1] = 0;
			sData[0].f[2] = 0;
			sData[0].f[3] = 0;
		}
	}
	NO_INLINE void sSFBlurFilterSize(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->blurParams.blurFilterSize.x;
			sData[0].f[1] = p->blurParams.blurFilterSize.y;
			sData[0].f[2] = p->blurParams.blurFilterSize.z;
			sData[0].f[3] = p->blurParams.blurFilterSize.w;
		}
	}
	NO_INLINE void sSFBlurFilerScale(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->blurParams.blurFilterScale.x;
			sData[0].f[1] = p->blurParams.blurFilterScale.y;
			sData[0].f[2] = 0;
			sData[0].f[3] = 0;
		}
	}
	NO_INLINE void sSFBlurFilerOffset(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->blurParams.blurFilterOffset.x;
			sData[0].f[1] = p->blurParams.blurFilterOffset.y;
			sData[0].f[2] = 0;
			sData[0].f[3] = 0;
		}
	}
	NO_INLINE void sSFBlurFilerColor1(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->blurParams.blurFilterColor1.r;
			sData[0].f[1] = p->blurParams.blurFilterColor1.g;
			sData[0].f[2] = p->blurParams.blurFilterColor1.b;
			sData[0].f[3] = p->blurParams.blurFilterColor1.a;
		}
	}
	NO_INLINE void sSFBlurFilerColor2(UFloat4 *sData, CD3D9Renderer *r)
	{
		const SSF_GlobalDrawParams* p(r->SF_GetGlobalDrawParams());
		assert(p);
		if (p)
		{
			sData[0].f[0] = p->blurParams.blurFilterColor2.r;
			sData[0].f[1] = p->blurParams.blurFilterColor2.g;
			sData[0].f[2] = p->blurParams.blurFilterColor2.b;
			sData[0].f[3] = p->blurParams.blurFilterColor2.a;
		}
	}
#endif

  NO_INLINE void sSpecularMulti(UFloat4 *sData)
  {
    SRenderLight *pDL;
    SLightPass *pLP;
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    pLP = &rRP.m_LPasses[rRP.m_nCurLightPass];
    for (uint32 i=0; i<pLP->nLights; i++)
    {
      pDL = pLP->pLights[i];
      sData[i].f[0] = pDL->m_Color[0] * pDL->m_Color.a;
      sData[i].f[1] = pDL->m_Color[1] * pDL->m_Color.a;
      sData[i].f[2] = pDL->m_Color[2] * pDL->m_Color.a;
      sData[i].f[3] = pDL->m_SpecMult;

      if (rRP.m_pShaderResources)
      {
        sData[i].f[0] *= rRP.m_pShaderResources->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][0];
        sData[i].f[1] *= rRP.m_pShaderResources->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][1];
        sData[i].f[2] *= rRP.m_pShaderResources->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][2];
      }

      if (rRP.m_pShaderResources && (rRP.m_pShaderResources->m_ResFlags & MTL_FLAG_ADDITIVE))
      {
        sData[i].f[0] *= rRP.m_fCurOpacity;
        sData[i].f[1] *= rRP.m_fCurOpacity;
        sData[i].f[2] *= rRP.m_fCurOpacity;
      }
    }
  }

  NO_INLINE void sLightPos(UFloat4 *sData)
  {
    SRenderLight *pDL;
    SLightPass *pLP;
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    pLP = &rRP.m_LPasses[rRP.m_nCurLightPass];
    for (uint32 i=0; i<pLP->nLights; i++)
    {
      pDL = pLP->pLights[i];
      Vec3 v = pDL->m_Origin - r->GetRCamera().Orig;
      sData[i].f[0] = v.x;
      sData[i].f[1] = v.y;
      sData[i].f[2] = v.z;

      float fRadius = pDL->m_fRadius;
      if (fRadius <= 0)
        fRadius = 1.f;
      sData[i].f[3] = 1.f / fRadius;
    }
  }

  NO_INLINE void sLightsNum(UFloat4 *sData, int nComp)
  {
    SLightPass *pLP;
    CD3D9Renderer *const __restrict r = gcpRendD3D;
    SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
    pLP = &rRP.m_LPasses[rRP.m_nCurLightPass];
    sData[0].f[nComp] = (float)pLP->nLights;
  }


}

void CRenderer::UpdateConstParamsPF( )
{
  // Per frame - hardcoded/fast - update of commonly used data - feel free to improve this
  int nThreadID = m_RP.m_nFillThreadID;

  SCGParamsPF &PF = gRenDev->m_cEF.m_PF;
  uint32 nFrameID = gRenDev->m_RP.m_TI[nThreadID].m_nFrameUpdateID;
  if( PF.nFrameID == nFrameID || SRendItem::m_RecurseLevel[nThreadID] > 1 )
    return;

  PF.nFrameID = nFrameID;

  // Updating..

  I3DEngine *p3DEngine = gEnv->p3DEngine;
  if (p3DEngine==NULL)
    return;


  // ECGP_PB_WaterLevel - x = static level y = dynamic water ocean/volume level based on camera position, z: dynamic ocean water level
  PF.vWaterLevel = Vec3(p3DEngine->GetWaterLevel(), p3DEngine->GetWaterLevel(), p3DEngine->GetWaterLevel() );//gEnv->p3DEngine->GetWaterLevel(&gRenDev->GetRCamera().Orig), p3DEngine->GetOceanWaterLevel(gRenDev->GetRCamera().Orig));

  // ECGP_PB_HDRDynamicMultiplier
  PF.fHDRDynamicMultiplier = p3DEngine->GetHDRDynamicMultiplier();

  PF.pVolumetricFogParams = sGetVolumetricFogParams(gcpRendD3D);
  PF.pVolumetricFogRampParams = sGetVolumetricFogRampParams();
  PF.pVolumetricFogSunDir = sGetVolumetricFogSunDir();

  sGetFogColorGradientConstants(PF.pFogColGradColBase, PF.pFogColGradColDelta);
  PF.pFogColGradParams = sGetFogColorGradientParams();
  PF.pFogColGradRadial = sGetFogColorGradientRadial(gcpRendD3D);

  // ECGP_PB_CausticsParams
  Vec4 vTmp = p3DEngine->GetCausticsParams();
  //PF.pCausticsParams = Vec3( vTmp.y, vTmp.z, vTmp.w );
  PF.pCausticsParams = Vec3( vTmp.x, vTmp.z, vTmp.y );

  // ECGP_PF_SunColor
  PF.pSunColor = p3DEngine->GetSunColor();
  // ECGP_PF_SkyColor
  PF.pSkyColor = p3DEngine->GetSkyColor();

  //ECGP_PB_CloudShadingColorSun
  Vec3 cloudShadingSunColor;
  p3DEngine->GetGlobalParameter(E3DPARAM_CLOUDSHADING_SUNCOLOR, cloudShadingSunColor);
  PF.pCloudShadingColorSun = cloudShadingSunColor;
  //ECGP_PB_CloudShadingColorSky
  Vec3 cloudShadingSkyColor;
  p3DEngine->GetGlobalParameter(E3DPARAM_CLOUDSHADING_SKYCOLOR, cloudShadingSkyColor);
  PF.pCloudShadingColorSky = cloudShadingSkyColor;

  // ECGP_PB_DecalZFightingRemedy
  float *mProj = (float *)gcpRendD3D->m_RP.m_TI[nThreadID].m_matProj->GetTop();
  float s = clamp_tpl(CRenderer::CV_r_ZFightingDepthScale, 0.1f, 1.0f);

  PF.pDecalZFightingRemedy.x = s; // scaling factor to pull decal in front
  PF.pDecalZFightingRemedy.y = (float)((1.0f - s) * mProj[4*3+2]); // correction factor for homogeneous z after scaling is applied to xyzw { = ( 1 - v[0] ) * zMappingRageBias }
  PF.pDecalZFightingRemedy.z = clamp_tpl(CRenderer::CV_r_ZFightingExtrude, 0.0f, 1.0f);

  // alternative way the might save a bit precision
  //PF.pDecalZFightingRemedy.x = s; // scaling factor to pull decal in front
  //PF.pDecalZFightingRemedy.y = (float)((1.0f - s) * mProj[4*2+2]);
  //PF.pDecalZFightingRemedy.z = clamp_tpl(CRenderer::CV_r_ZFightingExtrude, 0.0f, 1.0f);

  CEffectParam *pNVParam = PostEffectMgr()->GetByName("NightVision_Active"); 
	if (pNVParam)
	{
		PF.bPE_NVActive = pNVParam->GetParam() != 0.0f;
	}
}




























#if defined (DIRECT3D10) || defined(PS3)
std::vector<CHWShader_D3D::SCBuffer> CHWShader_D3D::m_CB_SI;
std::vector<ID3D11Buffer *> CHWShader_D3D::m_CB_SI_Released[CB_SI_MAXVECS];
std::vector<int> CHWShader_D3D::m_CB_SI_ReleasedID;

#ifdef _DEBUG
void CHWShader_D3D::mfValidateCB_SI(CRenderObject *pObj, CShader *pFXShader, int nMaxVecs)
{
  SCBuffer& cb = m_CB_SI[pObj->m_nCBID]; 
  Vec4 *pData = &cb.Vectors[0];
  Vec4 *vData = alias_cast<Vec4 *>(&sDataBuffer[16]);
  SCGParam *pParam = &pFXShader->m_InstParams[0];
  int nParams = pFXShader->m_InstParams.size();
  mfSetParametersPI(pParam, nParams, &vData[0][0], eHWSC_Vertex, nMaxVecs);
  assert(pParam->m_dwBind == 0);  // First should be matrix
  assert (pData[0] == vData[0]);
  assert (pData[1] == vData[1]);
  assert (pData[2] == vData[2]);
  pParam++;
  for (int i=1; i<nParams; i++, pParam++)
  {
    if (pParam->m_dwCBufSlot < 0)
      continue;
    assert(pData[i+2] == vData[i+2]);
  }
}
#endif

void CHWShader::mfReleaseCB_SI(int nCBID)
{
  ID3D11Buffer *pBuf = CHWShader_D3D::mfGetCB_SI_Interface(nCBID);
  assert(pBuf);
  if (!pBuf)
    return;
  D3D11_BUFFER_DESC Desc;
  pBuf->GetDesc(&Desc);
  int nVecs = Desc.ByteWidth >> 4;
  assert(nVecs < CB_SI_MAXVECS);
  CHWShader_D3D::m_CB_SI_Released[nVecs].push_back(pBuf);
  CHWShader_D3D::m_CB_SI_ReleasedID.push_back(nCBID);
}

int CHWShader_D3D::mfGetCB_SI(int nMaxVecs, CShader *pFXShader)
{
  ID3D11Buffer *pBuf = NULL;
  assert(nMaxVecs < CB_SI_MAXVECS);
  if (m_CB_SI_Released[nMaxVecs].size())
  {
    pBuf = m_CB_SI_Released[nMaxVecs][m_CB_SI_Released[nMaxVecs].size()-1];
    m_CB_SI_Released[nMaxVecs].pop_back();
  }
  else
  {
    D3D11_BUFFER_DESC bd;
    ZeroStruct(bd);
    HRESULT hr;
    bd.MiscFlags = 0;
    bd.ByteWidth = nMaxVecs * sizeof(Vec4);
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bd.CPUAccessFlags = 0;
    //bd.Usage = D3D11_USAGE_DYNAMIC;
    //bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    //bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    hr = gcpRendD3D->m_pd3dDevice->CreateBuffer(&bd, NULL, &pBuf);
  }
  assert(pBuf);
  SCBuffer cb;
  cb.nMask = pFXShader->m_nMaskCB;
  cb.pBuf = pBuf;
  int nID;
  if (m_CB_SI_ReleasedID.size())
  {
    nID = m_CB_SI_ReleasedID[m_CB_SI_ReleasedID.size()-1];
    m_CB_SI_ReleasedID.pop_back();
    assert(nID < m_CB_SI.size());
    m_CB_SI[nID] = cb;
  }
  else
  {
    nID = m_CB_SI.size();
    m_CB_SI.push_back(cb);
  }
  /*pBuf->Map(D3D11_MAP_WRITE_DISCARD, NULL, (void **)&pData);
  Vec4 *vData = (Vec4 *)&sData[16];
  const int nParams = pFXShader->m_InstParams.size();
  SCGParam *pParam = &pFXShader->m_InstParams[0];
  mfSetParametersPI(pParam, nParams, &vData[0][0], eHWSC_Vertex, nMaxVecs);
  assert(pParam->m_dwBind == 0);  // First should be matrix
  pData[0] = vData[0];
  pData[1] = vData[1];
  pData[2] = vData[2];
  pParam++;
  for (int i=1; i<nParams; i++, pParam++)
  {
    int nBind = pParam->m_dwBind>>2;
    pData[nBind] = vData[i+2];
  }
  pBuf->Unmap();*/
  static std::vector<Vec4> sVecData;
  sVecData.resize(nMaxVecs);
  Vec4 *pData = &sVecData[0];
	
  Vec4 *vData = alias_cast<Vec4*>(&sDataBuffer[16]);
  SCGParam *pParam = &pFXShader->m_InstParams[0];
  int nParams = pFXShader->m_InstParams.size();
  mfSetParametersPI(pParam, nParams, &vData[0][0], eHWSC_Vertex, nMaxVecs);
  assert(pParam->m_dwBind == 0);  // First should be matrix
  pData[0] = vData[0];
  pData[1] = vData[1];
  pData[2] = vData[2];
  
#ifdef _DEBUG
  SCBuffer &c = m_CB_SI[nID];
  c.Vectors.push_back(vData[0]);
  c.Vectors.push_back(vData[1]);
  c.Vectors.push_back(vData[2]);
#endif
  pParam++;
  for (int i=1; i<nParams; i++, pParam++)
  {
    if (pParam->m_dwCBufSlot < 0)
      continue;
    int nBind = pParam->m_dwBind;
    pData[nBind] = vData[i+2];
#ifdef _DEBUG
    c.Vectors.push_back(vData[i+2]);
#endif
  }
  gcpRendD3D->m_pd3dDeviceContext->UpdateSubresource(pBuf, 0, NULL, pData, 0, 0);

  return nID;
}
#endif

void CHWShader_D3D::mfCommitParamsMaterial()
{
  CD3D9Renderer *const __restrict rd = gcpRendD3D;
#if defined(DIRECT3D10)
  SRenderShaderResources *const __restrict pRes = rd->m_RP.m_pShaderResources;
  if (pRes)
  {
    bool bVSParams = m_pCurInstVS && m_pCurInstVS->m_bHasPMParams;
#if !defined(PS3) && !defined(XENON) && !defined(CAFE)
    if (m_pCurInstDS && m_pCurInstDS->m_bHasPMParams)
      bVSParams = true;
    else
    if (m_pCurInstHS && m_pCurInstHS->m_bHasPMParams)
      bVSParams = true;
#endif
    if (bVSParams)
    {
      SRenderObjData *const __restrict pOD =  rd->m_RP.m_pCurObject->GetObjData(rd->m_RP.m_nProcessThreadID);
      if (pOD && pOD->m_Constants.size())
      {
        mfSetCBConst(0, CB_PER_MATERIAL, eHWSC_Vertex, &pOD->m_Constants[0][0], pOD->m_Constants.size()*4, pOD->m_Constants.size());
        mfCommitCB(CB_PER_MATERIAL, eHWSC_Vertex, eHWSC_Vertex);
      }
      else
      {
        ID3D11Buffer *const __restrict pCB = (ID3D11Buffer *)pRes->m_pCB[eHWSC_Vertex];
        mfSetCB(eHWSC_Vertex, CB_PER_MATERIAL, pCB);
#if !defined(PS3) && !defined(XENON) && !defined(CAFE)
        if (CHWShader_D3D::m_pCurInstDS)
        {
          mfSetCB(eHWSC_Domain, CB_PER_MATERIAL, pCB);
          mfSetCB(eHWSC_Hull, CB_PER_MATERIAL, pCB);
        }
        if (CHWShader_D3D::m_pCurInstGS)
          mfSetCB(eHWSC_Geometry, CB_PER_MATERIAL, pCB);
        if (CHWShader_D3D::m_pCurInstCS)
          mfSetCB(eHWSC_Compute, CB_PER_MATERIAL, pCB);
#endif
      }
    }
    if (m_pCurInstPS && m_pCurInstPS->m_bHasPMParams)
    {
      ID3D11Buffer *const __restrict pCB = (ID3D11Buffer *)pRes->m_pCB[eHWSC_Pixel];
      mfSetCB(eHWSC_Pixel, CB_PER_MATERIAL, pCB);
    }
  }
#endif
}

void CHWShader_D3D::mfCommitParamsGlobal()
{
  PROFILE_FRAME(CommitGlobalShaderParams);

  CD3D9Renderer *const __restrict rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
#if defined (DIRECT3D9)
  if (rRP.m_PersFlags2 & RBPF2_COMMIT_PF)
  {
    rRP.m_PersFlags2 &= ~RBPF2_COMMIT_PF;
    mfSetSamplers(m_PF_Samplers, eHWSC_Pixel);
    mfSetPF();
  }
  if (rRP.m_PersFlags2 & RBPF2_COMMIT_CM)
  {
    rRP.m_PersFlags2 &= ~RBPF2_COMMIT_CM;
    mfSetCM();
  }
#elif defined(DIRECT3D10)
  if (rRP.m_PersFlags2 & (RBPF2_COMMIT_PF | RBPF2_COMMIT_CM))
  {
    rRP.m_PersFlags2 &= ~(RBPF2_COMMIT_PF | RBPF2_COMMIT_CM);
    mfSetSamplers(m_PF_Samplers, eHWSC_Pixel);
    mfSetPF(); // Per-frame parameters
    mfSetCM(); // Per-camera parameters
  }
  mfCommitCB(CB_PER_FRAME, eHWSC_Vertex, eHWSC_Vertex);
  mfCommitCB(CB_PER_SHADOWGEN, eHWSC_Vertex, eHWSC_Vertex);

  mfCommitCB(CB_PER_FRAME, eHWSC_Pixel, eHWSC_Pixel);
  mfCommitCB(CB_PER_SHADOWGEN, eHWSC_Pixel, eHWSC_Pixel);

  if (m_pCurReqCB[eHWSC_Pixel][CB_PER_LIGHT])
    mfSetCB(eHWSC_Pixel, CB_PER_LIGHT, m_pCurReqCB[eHWSC_Pixel][CB_PER_LIGHT]);
  if (m_pCurReqCB[eHWSC_Vertex][CB_PER_LIGHT])
    mfSetCB(eHWSC_Vertex, CB_PER_LIGHT, m_pCurReqCB[eHWSC_Vertex][CB_PER_LIGHT]);
 #if !defined(PS3) && !defined(CAFE)
  if (m_pCurInstGS)
    mfSetCB(eHWSC_Geometry, CB_PER_FRAME, m_pCurReqCB[eHWSC_Vertex][CB_PER_FRAME]);
  if (m_pCurInstHS)
  {
    mfSetCB(eHWSC_Hull, CB_PER_FRAME, m_pCurReqCB[eHWSC_Vertex][CB_PER_FRAME]);
    mfSetCB(eHWSC_Domain, CB_PER_FRAME, m_pCurReqCB[eHWSC_Vertex][CB_PER_FRAME]);
  }
  if (m_pCurReqCB[eHWSC_Geometry][CB_PER_LIGHT])
    mfSetCB(eHWSC_Geometry, CB_PER_LIGHT, m_pCurReqCB[eHWSC_Geometry][CB_PER_LIGHT]);
  if (m_pCurReqCB[eHWSC_Compute][CB_PER_LIGHT])
    mfSetCB(eHWSC_Compute, CB_PER_LIGHT, m_pCurReqCB[eHWSC_Compute][CB_PER_LIGHT]);
 #endif
#endif
}

void CHWShader_D3D::mfCommitParams()
{
	FUNCTION_PROFILER_RENDER_FLAT
  CD3D9Renderer *const __restrict rd = gcpRendD3D;
#if defined (DIRECT3D9)
  PROFILE_FRAME(CommitShaderParams);

  LPDIRECT3DDEVICE9 dv = rd->GetD3DDevice();
  int i;
  if (m_NumPSParamsToCommit > 0)
  {
    //std::sort(m_PSParamsToCommit, m_PSParamsToCommit+m_NumPSParamsToCommit);

    int nFirst = m_PSParamsToCommit[0];
    int nParams = 1;
		assert(nFirst < MAX_CONSTANTS_PS);
    const int32 nCommitParms = m_NumPSParamsToCommit;

    for (i=1; i<nCommitParms; i++)
    {
      if (m_PSParamsToCommit[i] != m_PSParamsToCommit[i-1]+1)
      {
        dv->SetPixelShaderConstantF(nFirst, &m_CurPSParams[nFirst].x, nParams);
        nFirst = m_PSParamsToCommit[i];
        nParams = 1;
      }
      else
        nParams++;
    }
		assert(nFirst < MAX_CONSTANTS_PS);
    dv->SetPixelShaderConstantF(nFirst, &m_CurPSParams[nFirst].x, nParams);
    m_NumPSParamsToCommit = 0;
  }

  if (m_NumVSParamsToCommit > 0)
  {
    //std::sort(m_VSParamsToCommit, m_VSParamsToCommit+m_NumVSParamsToCommit);

    int nFirst = m_VSParamsToCommit[0];
    int nParams = 1;
		assert(nFirst < MAX_CONSTANTS_VS);
    
		const int32 nCommitParms = m_NumVSParamsToCommit;
    for (i=1; i<nCommitParms; i++)
    {
      if (m_VSParamsToCommit[i] != m_VSParamsToCommit[i-1]+1)
      {
        dv->SetVertexShaderConstantF(nFirst, &m_CurVSParams[nFirst].x, nParams);
        nFirst = m_VSParamsToCommit[i];
        nParams = 1;
      }
      else
        nParams++;
    }
		assert(nFirst < MAX_CONSTANTS_VS);
    dv->SetVertexShaderConstantF(nFirst, &m_CurVSParams[nFirst].x, nParams);
		
    m_NumVSParamsToCommit = 0;
  }
#elif defined(DIRECT3D10)
  mfCommitCB(CB_PER_BATCH, eHWSC_Vertex, eHWSC_Vertex);
  mfCommitCB(CB_PER_INSTANCE, eHWSC_Vertex, eHWSC_Vertex);
#	if !defined(PS3) && !defined(CAFE)
  if (m_pCurInstDS)
  {
    // if seams fix is enabled, domain shader reads texture coordinates directly from buffer bypassing VS
    // so it may need to apply to texture coordinate the same kind of transformation that vertex shader is doing
    mfSetCB(eHWSC_Domain, CB_PER_INSTANCE, m_pCurReqCB[eHWSC_Vertex][CB_PER_INSTANCE]);
  }
#	endif
  mfCommitCB(CB_STATIC_INSTANCE, eHWSC_Vertex, eHWSC_Vertex);
  mfCommitCB(CB_SKIN_DATA, eHWSC_Vertex, eHWSC_Vertex);
  mfCommitCB(CB_SHAPE_DATA, eHWSC_Vertex, eHWSC_Vertex);

  mfCommitCB(CB_PER_BATCH, eHWSC_Pixel, eHWSC_Pixel);
  mfCommitCB(CB_PER_INSTANCE, eHWSC_Pixel, eHWSC_Pixel);
 #if !defined(PS3) && !defined(CAFE)
  if (m_pCurInstGS)
  {
    mfCommitCB(CB_PER_BATCH, eHWSC_Geometry, eHWSC_Geometry);
    mfCommitCB(CB_PER_INSTANCE, eHWSC_Geometry, eHWSC_Geometry);
  }
 #endif
 #ifdef _DEBUG
  for (int j=0; j<eHWSC_Num; j++)
  {
    for (int i=0; i<CB_NUM; i++)
    {
      assert(!m_pDataCB[j][i]);
    }
  }
 #endif
#endif




}


static char *sSH[] = {"VS", "PS", "GS"};
static char *sComp[] = {"x", "y", "z", "w"};

#if defined (DIRECT3D10)
float *CHWShader_D3D::mfSetInstancingParameters(SCGParam *pParams, const int nINParams, float *pDst, int nMaxVecs)
#else
float *CHWShader_D3D::mfSetInstancingParameters(SCGParam *pParams, const int nINParams, float *pDst)
#endif
{
	FUNCTION_PROFILER_RENDER_FLAT
	//regarding snTuner this line causes 30% of the function's time and this function is using 12% of the whole frame time
#if !defined(PS3)
  PROFILE_FRAME(Shader_SetParamsInstancing);
#endif





  if (!pParams || !pDst)
    return pDst;

  CD3D9Renderer *const __restrict r = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
	CRenderObject *const __restrict pObj = rRP.m_pCurObject;
	SRenderShaderResources *pRes=rRP.m_pShaderResources;

	// precache int to float conversions for some parameters
	CIntToFloat objDissolveRef(pObj->m_DissolveRef);
	CIntToFloat objRenderQuality(pObj->m_nRenderQuality);

  const SCGParam *__restrict ParamBind = pParams;
	
	union { UFloat4 *uf4; float *f; } u;
	u.f = pDst;

	UFloat4 *sData = u.uf4;

	const SInstanceInfo &rInstInfo = rRP.m_pCurObject->m_II;

	// loop unrolled assuming order of supported attributes in enum ECGParam in ShaderComponents.h
	// and sorting in HWShaderCompiling.cpp - CGBindCallback()
	// Must be kept in sync so the order is correct. In debug, assert on the order:
	assert(ECGP_SI_AmbientOpacity < ECGP_SI_ObjectAmbColComp);
	assert(ECGP_SI_ObjectAmbColComp < ECGP_PI_AlphaTest);
	assert(ECGP_PI_AlphaTest < ECGP_SI_BendInfo);
	assert(ECGP_SI_BendInfo < ECGP_PI_AvgFogVolumeContrib);
	assert(ECGP_PI_AvgFogVolumeContrib < ECGP_PI_HMAGradients);
	
	// count the attributes filled
	int nRemainingAttr = nINParams;

  // Not activated yet for this shader
#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_SI_AmbientOpacity)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);

		sAmbientOpacity(sData, rInstInfo);
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_SI_ObjectAmbColComp)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);

		sObjectAmbColComp(sData, rInstInfo, objRenderQuality.Convert());
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_PI_AlphaTest)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);
	
		sAlphaTest(sData, objDissolveRef.Convert());
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_SI_BendInfo)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);
		
		sGetBendInfo(sData, r);
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_PI_AvgFogVolumeContrib)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);
		
		sAvgFogVolumeContrib(sData);
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#if defined (DIRECT3D10) || defined(PS3)
	if(ParamBind->m_dwCBufSlot < 0)
	{
		ParamBind++;
	}
#endif

	if(nRemainingAttr && ParamBind->m_eCGParamType == ECGP_PI_HMAGradients)
	{
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);
		
		sHMAGradients(sData);
		sData++;

		ParamBind++;
		nRemainingAttr--;
	}

#ifdef _DEBUG
	assert(nRemainingAttr == 0);
#endif

  return pDst+nINParams*4;
}

#if defined (DIRECT3D10)
float *CHWShader_D3D::mfSetParametersPI(SCGParam *pParams, const int nINParams, float *pDst, EHWShaderClass eSH, int nMaxVecs)
#else
float *CHWShader_D3D::mfSetParametersPI(SCGParam *pParams, const int nINParams, float *pDst, EHWShaderClass eSH)
#endif
{
	/*
	FUNCTION_PROFILER_RENDER_FLAT
	//regarding snTuner this line causes 30% of the function's time and this function is using 12% of the whole frame time
#if !defined(PS3)
  PROFILE_FRAME(Shader_SetParamsPI);
#endif
	*/





  if (!pParams)
    return pDst;

  CD3D9Renderer *const __restrict r = gcpRendD3D;
  SCGParamsPF& RESTRICT_REFERENCE PF = r->m_cEF.m_PF;
  SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;
	CRenderObject *const __restrict pObj = rRP.m_pCurObject;

	// precache int to float conversions for some parameters
	CIntToFloat objDissolveRef(pObj->m_DissolveRef);
	CIntToFloat objRenderQuality(pObj->m_nRenderQuality);

  register float *pSrc, *pData;
  const SCGParam *__restrict ParamBind = pParams;
  int nParams;
  SEfResTexture *pRT;
  Vec3 v;

	const SInstanceInfo &rInstInfo = pObj->m_II;

	UFloat4 *sData = sDataBuffer;

  for (int nParam=0; nParam<nINParams; nParam++)
  {




#if defined (DIRECT3D10) || defined(PS3)
    // Not activated yet for this shader
    if (ParamBind->m_dwCBufSlot < 0)
    {
      ParamBind++;
      continue;
    }
#endif

    pSrc = &sData[0].f[0];
    nParams = ParamBind->m_nParameters;
    //uchar* egPrm  = ((uchar*)(ParamBind) + offsetof(SCGParam,m_eCGParamType));
    //int nCurType = *((uchar*)ParamBind); //->m_eCGParamType;
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);

#ifdef DO_RENDERLOG
    if (CRenderer::CV_r_log >= 3)
    {
      int nCurType = ParamBind->m_eCGParamType & 0xff;
      r->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], " Set %s parameter '%s:%s' (%d vectors, reg: %d)\n", sSH[eSH], "Unknown"/*ParamBind->m_Name.c_str()*/, r->m_cEF.mfGetShaderParamName((ECGParam)nCurType), nParams, ParamBind->m_dwBind);
    }
#endif

    switch(ParamBind->m_eCGParamType)
    {
      case ECGP_Matr_SI_Obj:
        {
          pData = (float *)rInstInfo.m_Matrix.GetData();





  #if defined(_CPU_SSE) && !defined(_DEBUG)
          sData[0].m128 = _mm_load_ps(&pData[0]);
          sData[1].m128 = _mm_load_ps(&pData[4]);
          sData[2].m128 = _mm_load_ps(&pData[8]);
  #else
          sData[0].f[0] = pData[0]; sData[0].f[1] = pData[1]; sData[0].f[2] = pData[2]; sData[0].f[3] = pData[3];
          sData[1].f[0] = pData[4]; sData[1].f[1] = pData[5]; sData[1].f[2] = pData[6]; sData[1].f[3] = pData[7];
          sData[2].f[0] = pData[8]; sData[2].f[1] = pData[9]; sData[2].f[2] = pData[10]; sData[2].f[3] = pData[11];




#endif
        }
  #if defined(CRY_DXPS_RASTERTHREAD)
        r->GetD3DDevice()->SoftRast().World(&sData[0].f[0]);
  #endif
        break;
      case ECGP_SI_AmbientOpacity:
        sAmbientOpacity(sData, rInstInfo);
        break;
      case ECGP_SI_BendInfo:  
        sGetBendInfo(sData, r);
        break;
      case ECGP_SI_ObjectAmbColComp:
        sObjectAmbColComp(sData, rInstInfo, objRenderQuality.Convert());
        break;

      case ECGP_Matr_PI_Obj_T:
        {
          Matrix44A* p = (Matrix44A*) &sData[0].f[0];
          assert(p); // needed for SCA without XENON_INTRINSICS defined
          *p = Matrix44A (rInstInfo.m_Matrix);
        }
        break;
      case ECGP_Matr_PI_ViewProj:
				{					
					if (!(rRP.m_ObjFlags & FOB_TRANS_MASK))
						alias_cast<Matrix44A*>(&sData[0])->Transpose(r->m_CameraProjMatrix);
					else
					{						
						mathMatrixMultiply_Transp2(&sData[4].f[0], r->m_CameraProjMatrix.GetData(), rInstInfo.m_Matrix.GetData(), g_CpuFlags);
						alias_cast<Matrix44A*>(&sData[0])->Transpose( *alias_cast<Matrix44A*>(&sData[4]) );
					}
					pSrc = &sData[0].f[0];
				}
        break;
      case ECGP_Matr_PI_TCMMatrix:
        {
          pRT = rRP.m_ShaderTexResources[ParamBind->m_nID];
          Matrix44A* p = (Matrix44A*) &sData[0].f[0];
          assert(p); // needed for SCA without XENON_INTRINSICS defined
//#ifndef CAFE
          if (pRT && pRT->m_Ext.m_pTexModifier)
            *p = pRT->m_Ext.m_pTexModifier->m_TexMatrix;
          else
//#else
//					OSREPORT("[CAFE WARNING] ECGP_Matr_PI_TCMMatrix not supported for CAFE. m_TexMatrix is not initialised and causes crashes e.g. if e_DefaultMaterial is set to 1/0.\n");
//#endif
          {
            //assert(0);
            *p = r->m_IdentityMatrix;
          }
        }
        break;
      case ECGP_PI_AlphaTest:
        sAlphaTest(sData, objDissolveRef.Convert());
        break;
      case ECGP_PI_Ambient:
				sAmbient(sData, rRP, rInstInfo);
        break;
      case ECGP_PI_TextureTileSize:
        sTextureTileSize(sData, rRP);
        break;
			case ECGP_PI_MotionBlurInfo:
				sMotionBlurInfo(sData, rRP);
				break;
			case ECGP_PI_ParticleParams:
				sParticleParams(sData, rRP);
				break;
      case ECGP_PI_HMAGradients:
        sHMAGradients(sData);
        break;
      case ECGP_PI_AvgFogVolumeContrib:
        sAvgFogVolumeContrib(sData);
        break;
      case ECGP_Matr_PI_Composite:
        {
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
          pMat->Multiply(*rRP.m_TI[rRP.m_nProcessThreadID].m_matView->GetTop(), *rRP.m_TI[rRP.m_nProcessThreadID].m_matProj->GetTop());
					pMat->Transpose(*pMat);
        }
        break;
      case ECGP_PI_MotionBlurData:        
        sGetMotionBlurData(sData, r, rInstInfo);
        break;
      case ECGP_PI_CloakParams:
        sGetCloakParams(sData, r, rInstInfo);
        break;
      case ECGP_PI_TessParams:
        sGetTessParams(sData, r);
        break;
      case ECGP_Matr_PI_TexMatrix:
        pSrc = sGetTexMatrix(sData, r, ParamBind);
        break;
      case ECGP_Matr_PI_TCGMatrix:
        {
          pRT = rRP.m_ShaderTexResources[ParamBind->m_nID];
          Matrix44A* p = (Matrix44A*) &sData[0].f[0];
          assert(p); // needed for SCA without XENON_INTRINSICS defined
//#ifndef CAFE
          if (pRT && pRT->m_Ext.m_pTexModifier)
            *p = pRT->m_Ext.m_pTexModifier->m_TexGenMatrix;
          else
//#else
//      OSREPORT("[CAFE WARNING] ECGP_Matr_PI_TCGMatrix not supported for CAFE. m_TexGenMatrix is not initialised and causes crashes e.g. if e_DefaultMaterial is set to 1/0.\n");
//#endif
          {
            //assert(0);
            *p = r->m_IdentityMatrix;
          }
        }
        break;
      case ECGP_PI_ObjColor:
        sData[0].f[0] = rInstInfo.m_AmbColor[0];
        sData[0].f[1] = rInstInfo.m_AmbColor[1];
        sData[0].f[2] = rInstInfo.m_AmbColor[2];
        sData[0].f[3] = rInstInfo.m_AmbColor[3] * rRP.m_pCurObject->m_fAlpha;
        break;
      case ECGP_PI_Wind:
        sGetWind(sData, r);
        break;
      case ECGP_PI_OSCameraPos:
        {
					Matrix44A *pMat1 = alias_cast<Matrix44A*>(&sData[4]);
					Matrix44A *pMat2 = alias_cast<Matrix44A*>(&sData[0]);
          pMat1->Transpose(rInstInfo.m_Matrix);					
          pMat2->Invert(*pMat1);
          TransformPosition(v, r->GetRCamera().Orig, *pMat2);
          sData[0].f[0] = v.x;
          sData[0].f[1] = v.y;
          sData[0].f[2] = v.z;
          sData[0].f[3] = 1.f;
        }
        break;
      case ECGP_PI_VisionParams:    
        sVisionParams(sData);
        break;
			case ECGP_PI_EffectLayerParams:
				sEffectLayerParams(sData);
				break;
      case ECGP_PI_MaterialLayersParams:
        sMaterialLayersParams(sData);
        break;
      case ECGP_PI_FrozenLayerParams:
        sGetFrozenParams(sData, r, rInstInfo);
        break;
	  case ECGP_PI_SnowVolumeParams:
		  sGetSnowVolumeParams(sData, r, rInstInfo);
		  break;
      case ECGP_PI_NumInstructions:
        sNumInstructions(sData);
        break;
      case ECGP_Matr_PI_OceanMat:
        sOceanMat(sData);
        break;
      default:
        assert(0);
        break;
    }
    if (pSrc)
    {
      if (pDst)
      {









#if defined(_CPU_SSE)
        const __m128 *__restrict cpSrc = (const __m128 *)pSrc;
        __m128 *__restrict cpDst = (__m128 *)pDst;
        const uint32 cParamCnt = nParams;
        for(uint32 i=0; i<cParamCnt; i++)
        {
          cpDst[i] = cpSrc[i];
        }
#else
        const float *const __restrict cpSrc = pSrc;
        float *const __restrict cpDst = pDst;
        const uint32 cParamCnt = nParams;
        for(uint32 i=0; i<cParamCnt; i+=4)
        {
          cpDst[i]	 = cpSrc[i];
          cpDst[i+1] = cpSrc[i+1];
          cpDst[i+2] = cpSrc[i+2];
          cpDst[i+3] = cpSrc[i+3];
        }
#endif
        pDst += cParamCnt*4;
      }
      else
      {
        // in WIN32 pData must be 16 bytes aligned
        assert(!((uint32)pSrc & 0xf) || sizeof(void *)!=4);
#if !defined (DIRECT3D10)



        if (!(ParamBind->m_Flags & PF_INTEGER))
          mfParameterfA(ParamBind, pSrc, nParams, eSH);
        else
          mfParameteri(ParamBind, pSrc, eSH);

#else
        if (!(ParamBind->m_Flags & PF_INTEGER))
          mfParameterfA(ParamBind, pSrc, nParams, eSH, nMaxVecs);
        else
          mfParameteri(ParamBind, pSrc, eSH, nMaxVecs);
#endif
      }
    }
    ParamBind++;
  }
  return pDst;
}

#if defined (DIRECT3D10)
void CHWShader_D3D::mfSetGeneralParametersPI(SCGParam *pParams, const int nINParams, EHWShaderClass eSH, int nMaxVecs)
#else
void CHWShader_D3D::mfSetGeneralParametersPI(SCGParam *pParams, const int nINParams, EHWShaderClass eSH)
#endif
{




  if (!pParams)
    return;

  CD3D9Renderer *const __restrict r = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

  register float *pSrc, *pData;
  const SCGParam *__restrict ParamBind = pParams;
  int nParams;

	UFloat4* sData = sDataBuffer;

  for (int nParam=0; nParam<nINParams; nParam++)
  {
    pSrc = &sData[0].f[0];
    nParams = ParamBind->m_nParameters;
    //uchar* egPrm  = ((uchar*)(ParamBind) + offsetof(SCGParam,m_eCGParamType));
    //int nCurType = *((uchar*)ParamBind); //->m_eCGParamType;
    assert (ParamBind->m_Flags & PF_SINGLE_COMP);

#ifdef DO_RENDERLOG
    if (CRenderer::CV_r_log >= 3)
    {
      int nCurType = ParamBind->m_eCGParamType & 0xff;
      r->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], " Set '%s' general parameter '%s:%s' (%d vectors, reg: %d)\n", sSH[eSH], "Unknown"/*ParamBind->m_Name.c_str()*/, r->m_cEF.mfGetShaderParamName((ECGParam)nCurType), nParams, ParamBind->m_dwBind);
    }
#endif

    switch(ParamBind->m_eCGParamType)
    {
    case ECGP_Matr_SI_Obj:
      {
        pData = rRP.m_pCurObject->m_II.m_Matrix.GetData();





#if defined(_CPU_SSE) && !defined(_DEBUG)
        sData[0].m128 = _mm_load_ps(&pData[0]);
        sData[1].m128 = _mm_load_ps(&pData[4]);
        sData[2].m128 = _mm_load_ps(&pData[8]);
#else
        sData[0].f[0] = pData[0]; sData[0].f[1] = pData[1]; sData[0].f[2] = pData[2]; sData[0].f[3] = pData[3];
        sData[1].f[0] = pData[4]; sData[1].f[1] = pData[5]; sData[1].f[2] = pData[6]; sData[1].f[3] = pData[7];
        sData[2].f[0] = pData[8]; sData[2].f[1] = pData[9]; sData[2].f[2] = pData[10]; sData[2].f[3] = pData[11];




#endif
      }
#if defined(CRY_DXPS_RASTERTHREAD)
      r->GetD3DDevice()->SoftRast().World(&sData[0].f[0]);
#endif
      break;
    case ECGP_SI_AmbientOpacity:
			sAmbientOpacity(sData, rRP.m_pCurObject->m_II);
      break;
    case ECGP_SI_BendInfo:  
      sGetBendInfo(sData, r);
      break;
    default:
      assert(0);
      break;
    }
    if (pSrc)
    {
      // in WIN32 pData must be 16 bytes aligned
      assert(!((uint32)pSrc & 0xf) || sizeof(void *)!=4);
#if !defined (DIRECT3D10)



      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH);
      else
        mfParameteri(ParamBind, pSrc, eSH);

#else



      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH, nMaxVecs);
      else
        mfParameteri(ParamBind, pSrc, eSH, nMaxVecs);

#endif
    }
    ParamBind++;
  }
}

#if defined (DIRECT3D10)
void CHWShader_D3D::mfSetGeneralParameters(SCGParam *pParams, const int nINParams, EHWShaderClass eSH, int nMaxVecs)
#else
void CHWShader_D3D::mfSetGeneralParameters(SCGParam *pParams, const int nINParams, EHWShaderClass eSH)
#endif
{




  const SCGParam *__restrict ParamBind = pParams;
  int nParams;
  register float *pSrc;

  CD3D9Renderer *const __restrict r = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

	UFloat4* sData = sDataBuffer;

  for (int nParam=0; nParam<nINParams; /*nParam++*/)
  {





    assert(ParamBind->m_Flags & PF_SINGLE_COMP);
    nParam++;

    pSrc = &sData[0].f[0];
    nParams = ParamBind->m_nParameters;

#ifdef DO_RENDERLOG
    if (CRenderer::CV_r_log >= 3)
      r->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], " Set '%s' general parameter '%s:%s' (%d vectors, reg: %d)\n", sSH[eSH], ParamBind->m_Name.c_str(), r->m_cEF.mfGetShaderParamName(ParamBind->m_eCGParamType), nParams, ParamBind->m_dwBind);
#endif
    switch (ParamBind->m_eCGParamType)
    {
    case ECGP_PM_Tweakable:
    case ECGP_PM_MatDiffuseColor:
    case ECGP_PM_MatSpecularColor:
      sTweakable(sData, ParamBind, eSH);
      break;

    case ECGP_PM_MatEmissiveColor:
      sMatEmissiveColor(sData, ParamBind, eSH);
      break;

    default:
      assert(0);
      break;
      //Warning("Unknown Parameter '%s' of type %d", ParamBind->m_Name.c_str(), ParamBind->m_eCGParamType);
      //assert(0);
      //return NULL;
    }
    if (pSrc)
    {
      // in WIN32 pData must be 16 bytes aligned
      assert(!((uint32)pSrc & 0xf) || sizeof(void *)!=4);
#if !defined (DIRECT3D10)



      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH);
      else
        mfParameteri(ParamBind, pSrc, eSH);

#else



      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH, nMaxVecs);
      else
        mfParameteri(ParamBind, pSrc, eSH, nMaxVecs);

#endif
    }
    ++ParamBind;
  }
}

#if defined (DIRECT3D10)
void CHWShader_D3D::mfSetParameters(SCGParam *pParams, const int nINParams, EHWShaderClass eSH, int nMaxVecs)
#else
void CHWShader_D3D::mfSetParameters(SCGParam *pParams, const int nINParams, EHWShaderClass eSH)
#endif
{
	/*
  PROFILE_FRAME(Shader_SetParams);
	FUNCTION_PROFILER_RENDER_FLAT
	*/





  CRendElementBase *pRE;
  register float *pSrc, *pData;
  Vec3 v;
	Vec4 v4;
  const SCGParam *ParamBind = pParams;
  int nParams;

  if (!pParams)
    return;

  CD3D9Renderer *const __restrict r = gcpRendD3D;
  SCGParamsPF &PF = r->m_cEF.m_PF;
  SRenderPipeline& RESTRICT_REFERENCE rRP = r->m_RP;

	UFloat4* sData = sDataBuffer;
	
  for (int nParam=0; nParam<nINParams; /*nParam++*/)
  {





		// saving HUGE LHS, x360 compiler generating quite bad code when nParam incremented inside for loop
		// note: nParam only used for previous line
		nParam++;

    pSrc = &sData[0].f[0];
    nParams = ParamBind->m_nParameters;
    //uchar* egPrm  = ((uchar*)(ParamBind) + offsetof(SCGParam,m_eCGParamType));
    //int nCurType = *((uchar*)ParamBind); //->m_eCGParamType;

		uint32 paramType = (uint32)ParamBind->m_eCGParamType;

    for (int nComp=0; nComp<4; nComp++)
    {
#ifdef DO_RENDERLOG
      if (CRenderer::CV_r_log >= 3)
      {
        int nCurType = (ParamBind->m_eCGParamType >> (nComp << 3)) & 0xff;
        if (ParamBind->m_Flags & PF_SINGLE_COMP)
          r->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], " Set %s parameter '%s:%s' (%d vectors, reg: %d)\n", sSH[eSH], ParamBind->m_Name.c_str(), r->m_cEF.mfGetShaderParamName((ECGParam)nCurType), nParams, ParamBind->m_dwBind);
        else
          r->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], " Set %s parameter '%s:%s' (%d vectors, reg: %d.%s)\n", sSH[eSH], ParamBind->m_Name.c_str(), r->m_cEF.mfGetShaderParamName((ECGParam)nCurType), nParams, ParamBind->m_dwBind, sComp[nComp]);
      }
#endif
      switch(paramType & 0xff)
      {
      case ECGP_Matr_PF_ViewProjMatrix:
				{					
					alias_cast<Matrix44A*>(&sData[0])->Transpose(r->m_CameraProjMatrix);
	#if defined(CRY_DXPS_RASTERTHREAD)
					r->GetD3DDevice()->ViewProjMatrix(pSrc);
	#endif
					break;
				}
			case ECGP_Matr_PF_ViewProjMatrixPrev:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
					pMat->Transpose(r->m_CameraProjMatrixPrevAvg);
					break;
				}
      case ECGP_Matr_PF_ViewProjZeroMatrix:
				{					
					alias_cast<Matrix44A*>(&sData[0])->Transpose(r->m_CameraProjZeroMatrix);
					break;
				}
      case ECGP_Matr_PB_ViewProjMatrix_I:
				{
					//mathMatrixInverse((float *)&sData[0].f[0], r->m_CameraProjMatrix.GetData(), g_CpuFlags);
					//mathMatrixTranspose(&sData[0].f[0], &sData[0].f[0], g_CpuFlags);
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
					pMat->Transpose(r->m_InvCameraProjMatrix);
					break;
				}
      case ECGP_Matr_PB_ViewProjMatrix_IT:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
					pMat->Invert(*pMat);
					//mathMatrixInverse((float *)&sData[0].f[0], r->m_CameraProjMatrix.GetData(), g_CpuFlags);
					break;
				}
      case ECGP_PF_FrustumPlaneEquation:
        {
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
          CCamera* pRC;
					const SRenderPipeline::ShadowInfo & shadowInfo = rRP.m_ShadowInfo;
					if ((rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN) && shadowInfo.m_pCurShadowFrustum)
					{
						assert(shadowInfo.m_nOmniLightSide >= 0 && shadowInfo.m_nOmniLightSide < OMNI_SIDES_NUM);
						pRC = &(shadowInfo.m_pCurShadowFrustum->FrustumPlanes[shadowInfo.m_nOmniLightSide]);
					}
					else
						pRC = &(rRP.m_TI[rRP.m_nProcessThreadID].m_cam);
						
          pMat->SetRow4(0, (Vec4 &)*pRC->GetFrustumPlane(FR_PLANE_RIGHT));
          pMat->SetRow4(1, (Vec4 &)*pRC->GetFrustumPlane(FR_PLANE_LEFT));
          pMat->SetRow4(2, (Vec4 &)*pRC->GetFrustumPlane(FR_PLANE_TOP));
          pMat->SetRow4(3, (Vec4 &)*pRC->GetFrustumPlane(FR_PLANE_BOTTOM));
          break;
        }
      case ECGP_PF_ShadowLightPos:
				if ((rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN) && rRP.m_ShadowInfo.m_pCurShadowFrustum)
				{
					const ShadowMapFrustum * pFrust = rRP.m_ShadowInfo.m_pCurShadowFrustum;
					const Vec3 vLPos = Vec3(
						pFrust->vLightSrcRelPos.x + pFrust->vProjTranslation.x,
						pFrust->vLightSrcRelPos.y + pFrust->vProjTranslation.y,
						pFrust->vLightSrcRelPos.z + pFrust->vProjTranslation.z
						);
					sData[0].f[0] = vLPos.x;
					sData[0].f[1] = vLPos.y;
					sData[0].f[2] = vLPos.z;
				}
        break;
			case ECGP_PF_ShadowViewPos:
				if ((rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN) && rRP.m_ShadowInfo.m_pCurShadowFrustum)
				{
					const Vec3 & vViewPos = rRP.m_ShadowInfo.vViewerPos;
					sData[0].f[0] = vViewPos.x;
					sData[0].f[1] = vViewPos.y;
					sData[0].f[2] = vViewPos.z;
				}
				break;

      case ECGP_Matr_PB_TerrainBase:
        pSrc = sGetTerrainBase(sData, r);
        break;
			case ECGP_PB_TerrainLayerSlope:
				pSrc = sGetTerrainLayerSlope(sData, r);
				break;
      case ECGP_Matr_PB_TerrainLayerGen:
        pSrc = sGetTerrainLayerGen(sData, r);
        break;
      case ECGP_Matr_PB_Temp4_0:
      case ECGP_Matr_PB_Temp4_1:
      case ECGP_Matr_PB_Temp4_2:
      case ECGP_Matr_PB_Temp4_3:
        pSrc = r->m_TempMatrices[ParamBind->m_eCGParamType-ECGP_Matr_PB_Temp4_0][ParamBind->m_nID].GetData();
        break;
      case ECGP_PB_DiffuseMulti:
        sDiffuseMulti(sData, rRP.m_pCurObject->m_II);
        break;
      case ECGP_PB_AmbientOpacity:
        sAmbientOpacity(sData, rRP.m_pCurObject->m_II);
        break;
      case ECGP_PB_FromRE:
        pRE = rRP.m_pRE;
        if (!pRE || !(pData=(float *)pRE->m_CustomData))
          sData[0].f[nComp] = 0;
        else
          sData[0].f[nComp] = pData[(ParamBind->m_nID>>(nComp*8))&0xff];
        break;
      case ECGP_PM_Tweakable:
      case ECGP_PM_MatDiffuseColor:
      case ECGP_PM_MatSpecularColor:
        sTweakable(sData, ParamBind, eSH);
        break;

      case ECGP_PM_MatEmissiveColor:
        sMatEmissiveColor(sData, ParamBind, eSH);
        break;

      case ECGP_PB_GlobalShaderFlag:
        assert(ParamBind->m_pData);
        if (ParamBind->m_pData)
        {
          if (!rRP.m_pShader)
            pData = NULL;
          else
          {
            bool bVal = (rRP.m_pShader->m_nMaskGenFX & ParamBind->m_pData->d.nData64[nComp]) != 0;
            sData[0].f[nComp] = (float)(bVal);
          }
        }
        break;
      case ECGP_PB_TempData:
        sGetTempData(sData, r, ParamBind);
        break;
      case ECGP_PB_VolumetricFogParams:
        sData[0].f[0] = PF.pVolumetricFogParams.x;
        sData[0].f[1] = PF.pVolumetricFogParams.y;
        sData[0].f[2] = PF.pVolumetricFogParams.z;
        sData[0].f[3] = PF.pVolumetricFogParams.w;
        break;
      case ECGP_PB_VolumetricFogRampParams:
        sData[0].f[0] = PF.pVolumetricFogRampParams.x;
        sData[0].f[1] = PF.pVolumetricFogRampParams.y;
        sData[0].f[2] = PF.pVolumetricFogRampParams.z;
        sData[0].f[3] = PF.pVolumetricFogRampParams.w;
        break;
      case ECGP_PB_FogColGradColBase:
        sData[0].f[0] = PF.pFogColGradColBase.x;
        sData[0].f[1] = PF.pFogColGradColBase.y;
        sData[0].f[2] = PF.pFogColGradColBase.z;
        sData[0].f[3] = 0.0f;
        break;
      case ECGP_PB_FogColGradColDelta:
        sData[0].f[0] = PF.pFogColGradColDelta.x;
        sData[0].f[1] = PF.pFogColGradColDelta.y;
        sData[0].f[2] = PF.pFogColGradColDelta.z;
        sData[0].f[3] = 0.0f;
        break;
      case ECGP_PB_FogColGradParams:
        sData[0].f[0] = PF.pFogColGradParams.x;
        sData[0].f[1] = PF.pFogColGradParams.y;
        sData[0].f[2] = PF.pFogColGradParams.z;
        sData[0].f[3] = PF.pFogColGradParams.w;
        break;
      case ECGP_PB_FogColGradRadial:
        sData[0].f[0] = PF.pFogColGradRadial.x;
        sData[0].f[1] = PF.pFogColGradRadial.y;
        sData[0].f[2] = PF.pFogColGradRadial.z;
        sData[0].f[3] = PF.pFogColGradRadial.w;
        break;
      case ECGP_PB_VolumetricFogSunDir:
        sData[0].f[0] = PF.pVolumetricFogSunDir.x;
        sData[0].f[1] = PF.pVolumetricFogSunDir.y;
        sData[0].f[2] = PF.pVolumetricFogSunDir.z;
        sData[0].f[3] = 0.0f;
        break;
      case ECGP_PB_RuntimeShaderFlag:
        assert(ParamBind->m_pData);
        if (ParamBind->m_pData)
        {
          bool bVal = (rRP.m_FlagsShader_RT & ParamBind->m_pData->d.nData64[nComp]) != 0;
          sData[0].f[nComp] = (float)(bVal);
        }
        break;

      case ECGP_Matr_PB_ProjMatrix:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        //*(Matrix44 *)(&sData[0].f[0]) = r->m_ProjMatrix;
		      pMat->Transpose(r->m_ProjMatrix);
			    break;
				}
      case ECGP_Matr_PB_UnProjMatrix:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Multiply(*rRP.m_TI[rRP.m_nProcessThreadID].m_matView->GetTop(), *rRP.m_TI[rRP.m_nProcessThreadID].m_matProj->GetTop());
		      pMat->Invert(*pMat);
			    pMat->Transpose(*pMat);
				  break;
				}
      case ECGP_Matr_PB_View_IT:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Multiply(GetTransposed44A(rRP.m_pCurObject->m_II.m_Matrix), r->m_CameraMatrix);
		      pMat->Invert(*pMat);
			    break;
				}
      case ECGP_Matr_PB_View:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Multiply(GetTransposed44A(rRP.m_pCurObject->m_II.m_Matrix), r->m_CameraMatrix);
		      pMat->Transpose(*pMat);
			    break;
				}
      case ECGP_Matr_PB_View_I:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Multiply(GetTransposed44A(rRP.m_pCurObject->m_II.m_Matrix), r->m_CameraMatrix);
		      pMat->Invert(*pMat);
			    pMat->Transpose(*pMat);
				  break;
				}
      case ECGP_Matr_PB_View_T:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
					pMat->Multiply(GetTransposed44A(rRP.m_pCurObject->m_II.m_Matrix), r->m_CameraMatrix);
		      break;
				}
      case ECGP_Matr_PB_Camera:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Transpose(r->m_CameraMatrix);
		      break;
				}
      case ECGP_Matr_PB_Camera_T:
        pSrc = r->m_CameraMatrix.GetData();
        break;
      case ECGP_Matr_PB_Camera_I:       
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Invert(r->m_CameraMatrix);
		      pMat->Transpose(*pMat);
			    break;
				}
      case ECGP_Matr_PB_Camera_IT:
				{
					Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
	        pMat->Invert(r->m_CameraMatrix);
		      break;
				}
      case ECGP_Matr_PB_LightMatrix:
        pSrc = sGetLightMatrix(sData, r);
        break;
      case ECGP_Matr_PB_VoxTerrainAtlasInfo:
        pSrc = sGetVoxTerrainAtlasInfo(sData, r);
        break;
      case ECGP_PL_LightsPos:
        sLightPos(sData);
        break;

      case ECGP_PL_LightsNum:
        assert(0);
        break;

      case ECGP_PF_TessInfo:
        sGetTessParams(sData, r);
        break;

      case ECGP_PL_ShadowMasks:
        sShadowMask(sData);
        break;
      case ECGP_PB_SpecularMulti:
        sSpecularMulti(sData);
        break;
      case ECGP_PL_LDiffuseColors:
        assert(0);
        break;
      case ECGP_PL_LSpecularColors:
        assert(0);
        break;
      case ECGP_PB_LightningPos:
        gEnv->p3DEngine->GetGlobalParameter(E3DPARAM_SKY_HIGHLIGHT_POS, v);
        sData[0].f[0] = v.x;
        sData[0].f[1] = v.y;
        sData[0].f[2] = v.z;
        sData[0].f[3] = 0.0f;
        break;
      case ECGP_PB_LightningColSize:
        sLightningColSize(sData);
        break;
      case ECGP_PB_LightsNum:
        sLightsNum(sData, nComp);
        break;
      case ECGP_PB_WaterLevel:
        sData[0].f[0] = PF.vWaterLevel.x;
        sData[0].f[1] = PF.vWaterLevel.y;
        sData[0].f[2] = PF.vWaterLevel.z;
        sData[0].f[3] = 1.0f;
        break;
      case ECGP_PB_HDRDynamicMultiplier:
        sData[0].f[nComp] = PF.fHDRDynamicMultiplier;
        break;
			case ECGP_PB_ObjVal:
				{
					SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
					if (pOD)
					{
						pData = (float *)pOD->m_fTempVars;
						sData[0].f[nComp] = pData[(ParamBind->m_nID>>(nComp*8))&0xff];
					}
				}
				break;
			case ECGP_PB_OutdoorAOParams:
				{
					SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(rRP.m_nProcessThreadID);
					if (pOD)
					{
						float * pObjTmpVars = pOD->m_fTempVars;
						sData[0].f[0] = gEnv->p3DEngine->GetSkyBrightness();
						sData[0].f[1] = pObjTmpVars[2]; // outdoor AO texgen scale
						sData[0].f[2] = pObjTmpVars[4]-pObjTmpVars[3]; // z range
						sData[0].f[3] = 0.f;//unused
					}
				}
				break;
      case ECGP_PB_RotGridScreenOff:
        sGetRotGridScreenOff(sData, r);
        break;
      case ECGP_PB_GlowParams:
        // to be merged with glow color/diffuse/emissive in future
        if (rRP.m_pShaderResources)
        {
          sData[0].f[0] = rRP.m_pShaderResources->Glow(); 

					if( /*CRenderer::CV_r_glow == 2 && */gRenDev->IsHDRModeEnabled() )
					{						
						float fPowFactor = gEnv->p3DEngine->GetHDRDynamicMultiplier();
						if (gRenDev->IsLinearSpaceShadingEnabled())
							sData[0].f[0] *= fPowFactor;

						sData[0].f[0] = powf( sData[0].f[0], fPowFactor);
					}

          sData[0].f[1] = sData[0].f[0];
          sData[0].f[2] = sData[0].f[0];
          sData[0].f[3] = 1.0f;
        }
        else
          sZeroLine(sData);
        break;
			case	ECGP_PB_StereoParams:
				if (gRenDev->IsStereoEnabled())
				{
					sData[0].f[0] = gcpRendD3D->GetS3DRend().GetMaxSeparationScene() * (gcpRendD3D->GetS3DRend().GetCurrentEye() == LEFT_EYE ? 1 : -1);
					sData[0].f[1] = gcpRendD3D->GetS3DRend().GetZeroParallaxPlaneDist();
					sData[0].f[2] = gcpRendD3D->GetS3DRend().GetNearGeoShift();
					sData[0].f[3] = gcpRendD3D->GetS3DRend().GetNearGeoScale();
				}
				else
					sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = 0;
				break;
      case ECGP_PB_DetailParams:
        sDetailParams(sData);
        break;
      case ECGP_PB_FurParams:
        sFurParams(sData);
        break;
      case ECGP_PB_IrregKernel:
        sGetIrregKernel(sData, r);
        break;
      case ECGP_PB_RegularKernel:
        sGetRegularKernel(sData, r);
        break;
      case ECGP_PB_DeformWaveX:
        {
          if (rRP.m_pShaderResources && rRP.m_pShaderResources->m_pDeformInfo)
          {
            SDeformInfo *di = rRP.m_pShaderResources->m_pDeformInfo;
            if (di->m_fDividerX != 0)
            {
              sData[0].f[0] = rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime*di->m_WaveX.m_Freq+di->m_WaveX.m_Phase;
              sData[0].f[1] = di->m_WaveX.m_Amp;
              sData[0].f[2] = di->m_WaveX.m_Level;
              sData[0].f[3] = 1.0f / di->m_fDividerX;
            }
            else
              sIdentityLine(sData);
          }
          else
            sIdentityLine(sData);
        }
        break;
      case ECGP_PB_DeformWaveY:
        {
          if (rRP.m_pShaderResources && rRP.m_pShaderResources->m_pDeformInfo)
          {
            SDeformInfo *di = r->m_RP.m_pShaderResources->m_pDeformInfo;
            if (di->m_fDividerY != 0)
            {
              sData[0].f[0] = rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime*di->m_WaveY.m_Freq+di->m_WaveY.m_Phase;
              sData[0].f[1] = di->m_WaveY.m_Amp;
              sData[0].f[2] = di->m_WaveY.m_Level;
              sData[0].f[3] = 1.0f / di->m_fDividerY;
            }
            else
              sIdentityLine(sData);
          }
          else
            sIdentityLine(sData);
        }
        break;
			case ECGP_PB_DeformFrequencies:
				{
					SRenderShaderResources *const __restrict pSR = rRP.m_pShaderResources;
					if (pSR && pSR->m_pDeformInfo)
					{
						SDeformInfo *const __restrict di = pSR->m_pDeformInfo;    
						sZeroLine(sData);

						float &fRealtime = rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;
						if (di->m_fDividerX != 0)
							sData[0].f[0] = fRealtime * di->m_WaveX.m_Freq + di->m_WaveX.m_Phase;
						if (di->m_fDividerY != 0)
							sData[0].f[1] = fRealtime * di->m_WaveY.m_Freq + di->m_WaveY.m_Phase;
						if (di->m_fDividerZ != 0)
							sData[0].f[2] = fRealtime * di->m_WaveZ.m_Freq + di->m_WaveZ.m_Phase;
						if (di->m_fDividerW != 0)    
							sData[0].f[3] = fRealtime * di->m_WaveW.m_Freq + di->m_WaveW.m_Phase;
					}
					else
						sZeroLine(sData);
				}
				break;

			case ECGP_PB_DeformAmplitudes:
				{
					SRenderShaderResources *const __restrict pSR = rRP.m_pShaderResources;
					if (pSR && pSR->m_pDeformInfo)
					{
						SDeformInfo *const __restrict di = pSR->m_pDeformInfo;
						sZeroLine(sData);

						if (di->m_fDividerX != 0)
							sData[0].f[0] = di->m_WaveX.m_Amp;
						if (di->m_fDividerY != 0)
							sData[0].f[1] = di->m_WaveY.m_Amp;
						if (di->m_fDividerZ != 0)
							sData[0].f[2] = di->m_WaveZ.m_Amp;
						if (di->m_fDividerW != 0)
							sData[0].f[3] = di->m_WaveW.m_Amp;
					}
					else
						sZeroLine(sData);
				}
				break;

			case ECGP_PB_DeformLevels:
				{
					SRenderShaderResources *const __restrict pSR = rRP.m_pShaderResources;
					if (pSR && pSR->m_pDeformInfo)
					{
						SDeformInfo *const __restrict di = pSR->m_pDeformInfo;
						sZeroLine(sData);

						if (di->m_fDividerX != 0)
							sData[0].f[0] = di->m_WaveX.m_Level;
						if (di->m_fDividerY != 0)
							sData[0].f[1] = di->m_WaveY.m_Level;
						if (di->m_fDividerZ != 0)
							sData[0].f[2] = di->m_WaveZ.m_Level;
						if (di->m_fDividerW != 0)
							sData[0].f[3] = di->m_WaveW.m_Level;
					}
					else
						sZeroLine(sData);
				}
				break;

			case ECGP_PB_DeformVertexPhases:
				{
					SRenderShaderResources *const __restrict pSR = rRP.m_pShaderResources;
					if (pSR && pSR->m_pDeformInfo)
					{
						SDeformInfo *const __restrict di = pSR->m_pDeformInfo;
						sZeroLine(sData);

						if (di->m_fDividerX != 0)
							sData[0].f[0] = 1.0f / di->m_fDividerX;
						if (di->m_fDividerY != 0)
							sData[0].f[1] = 1.0f / di->m_fDividerY;
						if (di->m_fDividerZ != 0)
							sData[0].f[2] = 1.0f / di->m_fDividerZ;
						if (di->m_fDividerW != 0)
							sData[0].f[3] = 1.0f / di->m_fDividerW;
					}
					else
						sZeroLine(sData);
				}
				break;
      case ECGP_PB_DeformBend:
        if (rRP.m_pShaderResources && rRP.m_pShaderResources->m_pDeformInfo)
        {
          SDeformInfo *di = rRP.m_pShaderResources->m_pDeformInfo;
          sData[0].f[0] = CShaderMan::EvalWaveForm(&di->m_WaveX);
          sData[0].f[1] = CShaderMan::EvalWaveForm(&di->m_WaveY);
          sData[0].f[2] = di->m_fDividerX;
          sData[0].f[3] = di->m_fDividerY;
        }
        else
          sIdentityLine(sData);
        break;
      case ECGP_PB_DeformNoiseInfo:
        if (rRP.m_pShaderResources && rRP.m_pShaderResources->m_pDeformInfo)
        {
          SDeformInfo *di = r->m_RP.m_pShaderResources->m_pDeformInfo;
          sData[0].f[0] = di->m_vNoiseScale[0] * rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;
          sData[0].f[1] = di->m_vNoiseScale[1] * rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;
          sData[0].f[2] = di->m_vNoiseScale[2] * rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;
          sData[0].f[3] = 1.0f;
        }
        else
          sIdentityLine(sData);
        break;
      case ECGP_PB_TFactor:
        sData[0].f[0] = r->m_RP.m_CurGlobalColor[0];
        sData[0].f[1] = r->m_RP.m_CurGlobalColor[1];
        sData[0].f[2] = r->m_RP.m_CurGlobalColor[2];
        sData[0].f[3] = r->m_RP.m_CurGlobalColor[3];
        break;
      case ECGP_PB_RandomParams:
        {
          sData[0].f[0] = Random();
          sData[0].f[1] = Random();
          sData[0].f[2] = Random();
          sData[0].f[3] = Random();
        }
        break;
      case ECGP_Matr_SG_ShadowProj_0:
        pSrc = r->m_TempMatrices[0][0].GetData();
        break;
      case ECGP_Matr_SG_ShadowProj_1:
        pSrc = r->m_TempMatrices[1][0].GetData();
        break;
      case ECGP_Matr_SG_ShadowProj_2:
        pSrc = r->m_TempMatrices[2][0].GetData();
        break;
      case ECGP_Matr_SG_ShadowProj_3:
        pSrc = r->m_TempMatrices[3][0].GetData();
        break;
      case ECGP_SG_FrustrumInfo:
        sData[0].f[0] = rRP.m_TI[rRP.m_nProcessThreadID].m_vFrustumInfo.x;
        sData[0].f[1] = rRP.m_TI[rRP.m_nProcessThreadID].m_vFrustumInfo.y;
        sData[0].f[2] = rRP.m_TI[rRP.m_nProcessThreadID].m_vFrustumInfo.z;
        sData[0].f[3] = rRP.m_TI[rRP.m_nProcessThreadID].m_vFrustumInfo.w;
        break;
      case ECGP_PB_DecalZFightingRemedy:
        sData[0].f[0] = PF.pDecalZFightingRemedy.x;
        sData[0].f[1] = PF.pDecalZFightingRemedy.y;
        sData[0].f[2] = PF.pDecalZFightingRemedy.z;
        sData[0].f[3] = 0;
				// specific condition for decals rendering into shadow map
				if (rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN)
				{
					sData[0].f[0] = 0.99997f;
					sData[0].f[1] = 0.f;
					sData[0].f[2] = 0.f;
				}
        break;
      case ECGP_PB_CameraFront:
        sCameraFront(sData, r);
        break;
      case ECGP_PB_CameraRight:
        sCameraRight(sData, r);
        break;
      case ECGP_PB_CameraUp:
        sCameraUp(sData, r);
        break;
      case ECGP_PB_RTRect:
        sRTRect(sData, r);
        break;
      case ECGP_PB_ResourcesOpacity:
        if (rRP.m_pShaderResources)
        {
          sData[0].f[0] = r->m_RP.m_pShaderResources->Opacity();
          sData[0].f[1] = sData[0].f[0];
          sData[0].f[2] = sData[0].f[0];
          sData[0].f[3] = sData[0].f[0];
        }
        else
          sZeroLine(sData);
        break;
      case ECGP_PB_Scalar:
        assert(ParamBind->m_pData);
        if (ParamBind->m_pData)
          sData[0].f[nComp] = ParamBind->m_pData->d.fData[nComp];
        break;

      case ECGP_PB_CausticsParams:
        sData[0].f[0] = CRenderer::CV_r_watercausticsdistance;//PF.pCausticsParams.x;
        sData[0].f[1] = PF.pCausticsParams.y;
        sData[0].f[2] = PF.pCausticsParams.z;				
        sData[0].f[3] = PF.pCausticsParams.x;
				//sData[0].f[3] = 1.0f;
        break;
/*
			case ECGP_PB_MotionBlurFrameData:        
				{
					// renormalize frametime to account for time scaling
					float fCurrFrameTime = gEnv->pTimer->GetFrameTime();      
					float fTimeScale = gEnv->pTimer->GetTimeScale();
					if (fTimeScale < 1.0f)
					{
						fTimeScale = max(0.0001f, fTimeScale);
						fCurrFrameTime /= fTimeScale; 
					}

					float fAlpha = 0.0f;
					float fExposureTime = CRenderer::CV_r_MotionBlurShutterSpeed;
					if(fCurrFrameTime != 0.0f)
						fAlpha = fExposureTime / fCurrFrameTime;  

					if( CRenderer::CV_r_MotionBlurFrameTimeScale )
					{
						float fAlphaScale = iszero(fCurrFrameTime) ? 1.0f : min(1.0f, (1.0f / fCurrFrameTime) / ( 32.0f)); // attenuate motion blur for lower frame rates
						fAlpha *= fAlphaScale;
					}

					sData[0].f[0] = sData[0].f[1] = sData[0].f[2] = sData[0].f[3] = fAlpha;

					break;
				}
*/
      case ECGP_PF_SunColor:
        {
          I3DEngine* pEng = gEnv->p3DEngine;
          v = pEng->GetSunColor();
          sData[0].f[0] = v.x;
          sData[0].f[1] = v.y;
          sData[0].f[2] = v.z;
          sData[0].f[3] = 1.0f / (r->m_fAdaptedSceneScaleLBuffer + FLT_MIN);
          break;
        }
      case ECGP_PF_SkyColor:
        sSkyColor(sData);
        break;

      case ECGP_PB_CausticsSmoothSunDirection:
        sCausticsSmoothSunDirection(sData);
        break;

      case ECGP_PF_SunDirection:
        sSunDirection(sData);
        break;
      case ECGP_PF_FogColor:
        v4 = sGetVolumetricFogParams(r);
        sData[0].f[3] = v4.z;
        sData[0].f[0] = rRP.m_TI[rRP.m_nProcessThreadID].m_FS.m_CurColor[0];
        sData[0].f[1] = rRP.m_TI[rRP.m_nProcessThreadID].m_FS.m_CurColor[1];
        sData[0].f[2] = rRP.m_TI[rRP.m_nProcessThreadID].m_FS.m_CurColor[2];
        //sData[0].f[3] = r->m_fAdaptedSceneScale;
        break;
      case ECGP_PF_CameraPos:
        v = r->GetRCamera().Orig;
        sData[0].f[0] = v.x;
        sData[0].f[1] = v.y;
        sData[0].f[2] = v.z;
        sData[0].f[3] = 1.f;
        break;
      case ECGP_PF_ScreenSize:
        sGetScreenSize(sData, r);
        break;
      case ECGP_PF_Time:
        //sData[0].f[nComp] = r->m_RP.m_ShaderCurrTime; //r->m_RP.m_RealTime;
        sData[0].f[nComp] = rRP.m_TI[rRP.m_nProcessThreadID].m_RealTime;
        assert(ParamBind->m_pData);
        if (ParamBind->m_pData)
          sData[0].f[nComp] *= ParamBind->m_pData->d.fData[nComp];
        break;
      case ECGP_PF_FrameTime:
        sData[0].f[nComp] = 1.f / gEnv->pTimer->GetFrameTime();
        assert(ParamBind->m_pData);
        if (ParamBind->m_pData)
          sData[0].f[nComp] *= ParamBind->m_pData->d.fData[nComp];
        break;
			case ECGP_PF_ProjRatio:
				{
					const CRenderCamera& rc = r->GetRCamera();
					float zn = rc.Near;
					float zf = rc.Far;
					float hfov = r->GetCamera().GetHorizontalFov();
					sData[0].f[0] = zf/(zf-zn);
					sData[0].f[1] = zn/(zn-zf);
					sData[0].f[2] = 1.0f / hfov;
					sData[0].f[3] = 1.0f;
				}
				break;
			case ECGP_PF_NearestScaled:
				{
					const CRenderCamera& rc = r->GetRCamera();
					I3DEngine *pEng = gEnv->p3DEngine;

					float zn = rc.Near;
					float zf = rc.Far;

					//////////////////////////////////////////////////////////////////////////
					float fNearZRange = r->CV_r_DrawNearZRange;
					float fCamScale = (r->CV_r_DrawNearFarPlane/pEng->GetMaxViewDistance());

					//float fDevDepthScale = 1.0f/fNearZRange;
					float fCombinedScale = fNearZRange*fCamScale;
					//float2 ProjRatioScale = float2((1.0f/fDevDepthScale), fCombinedScale);
					//////////////////////////////////////////////////////////////////////////

					sData[0].f[0] = zf/(zf-zn) * fNearZRange;
					sData[0].f[1] = zn/(zn-zf) * fNearZRange*fNearZRange;// fCombinedScale;
					sData[0].f[2] = fNearZRange - 0.001f;
					sData[0].f[3] = 1.0f;

				}
				break;
      case ECGP_PF_DepthFactor:
        sDepthFactor(sData, r);
        break;
      case ECGP_PF_NearFarDist:
        sNearFarDist(sData, r);
        break;
#ifndef EXCLUDE_SCALEFORM_SDK
      case ECGP_Matr_PB_SFCompMat:
        sSFCompMat(sData, r);
        break;
      case ECGP_Matr_PB_SFTexGenMat0:
        sSFTexGenMat0(sData, r);
        break;
      case ECGP_Matr_PB_SFTexGenMat1:
        sSFTexGenMat1(sData, r);
        break;
      case ECGP_PB_SFBitmapColorTransform:
        sSFBitmapColorTransform(sData, r);
        break;
			case ECGP_PB_SFColorTransformMatrix:
				sSFColorTransformMatrix(sData, r);
				break;
      case ECGP_PB_SFStereoVideoFrameSelect:
        sSFStereoVideoFrameSelect(sData, r);
        break;
			case ECGP_PB_SFPremultipliedAlpha:
				sSFPremultipliedAlpha(sData, r);
				break;
			case ECGP_PB_SFBlurFilterSize:
				sSFBlurFilterSize(sData, r);
				break;
			case ECGP_PB_SFBlurFilterScale:
				sSFBlurFilerScale(sData, r);
				break;
			case ECGP_PB_SFBlurFilterOffset:
				sSFBlurFilerOffset(sData, r);
				break;
			case ECGP_PB_SFBlurFilterColor1:
				sSFBlurFilerColor1(sData, r);
				break;
			case ECGP_PB_SFBlurFilterColor2:
				sSFBlurFilerColor2(sData, r);
				break;
#endif
      case ECGP_PB_CloudShadingColorSun:
        sData[0].f[0] = PF.pCloudShadingColorSun.x;
        sData[0].f[1] = PF.pCloudShadingColorSun.y;
        sData[0].f[2] = PF.pCloudShadingColorSun.z;
        sData[0].f[3] = 0;
        break;

      case ECGP_PB_CloudShadingColorSky:
        sData[0].f[0] = PF.pCloudShadingColorSky.x;
        sData[0].f[1] = PF.pCloudShadingColorSky.y;
        sData[0].f[2] = PF.pCloudShadingColorSky.z;
        sData[0].f[3] = 0;
        break;

      case ECGP_PB_AlphaTest:
				{
					sData[0].f[0] = 0;
					sData[0].f[1] = rRP.m_pCurObject->m_ObjFlags & FOB_DISSOLVE_OUT ? 1.0f : -1.0f;
					sData[0].f[2] = 0;
					sData[0].f[3] = rRP.m_pShaderResources ? rRP.m_pShaderResources->m_AlphaRef : 0;
					// specific condition for hair zpass
					if ((rRP.m_pShader->m_Flags2 & EF2_HAIR) && !(rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN))
						sData[0].f[3] = 0.51f;
					// specific condition for particles
					if (!rRP.m_pShaderResources && (rRP.m_nPassGroupID == EFSLIST_TRANSP || rRP.m_nPassGroupID == EFSLIST_HALFRES_PARTICLES))
					{
						const SRenderObjData *pOD = rRP.m_pCurObject->GetObjData(r->m_RP.m_nProcessThreadID);
						sData[0].f[3] = pOD->m_fTempVars[9];
					}
				}
        break;
			case ECGP_PB_ResInfoDiffuse:
        sResInfoDiffuse(sData);
  			break;
			case ECGP_PB_ResInfoBump:
        sResInfoBump(sData);
  			break;
			case ECGP_PB_TexelDensityParam:
        sTexelDensityParam(sData);
  			break;
			case ECGP_PB_TexelDensityColor:
        sTexelDensityColor(sData);
  			break;
			case ECGP_PB_TexelsPerMeterInfo:
        sTexelsPerMeterInfo(sData);
				break;
			case ECGP_PB_VisionMtlParams:
				sVisionMtlParams(sData);
				break;
			case ECGP_Matr_PB_GIGridMatrix:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
						if(pGIVolume)
						{
							Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
							*pMat = pGIVolume->GetRenderSettings().m_mat;
						}
					}
					break;
				}
			case ECGP_Matr_PB_GIInvGridMatrix:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
						if(pGIVolume)
						{
							Matrix44A *pMat = alias_cast<Matrix44A*>(&sData[0]);
							*pMat = pGIVolume->GetRenderSettings().m_matInv;
						}
					}
					break;
				}
			case ECGP_PB_GIGridSize:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
            if(pGIVolume)
            {
              const Vec4& vSize = pGIVolume->GetRenderSettings().m_gridDimensions;
              sData[0].f[0] = vSize.x;
              sData[0].f[1] = vSize.y;
              sData[0].f[2] = vSize.z;
              sData[0].f[3] = vSize.w;
            }
          }
					break;
				}
			case ECGP_PB_GIInvGridSize:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
            if(pGIVolume)
            {
              const Vec4& vInvSize = pGIVolume->GetRenderSettings().m_invGridDimensions;
              sData[0].f[0] = vInvSize.x;
              sData[0].f[1] = vInvSize.y;
              sData[0].f[2] = vInvSize.z;
              sData[0].f[3] = vInvSize.w;
            }
          }
					break;
				}
			case ECGP_PB_GIGridSpaceCamPos:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
            if(pGIVolume)
            {
              const Vec4 vGridSpaceCamPos(pGIVolume->GetRenderSettings().m_mat.TransformPoint(gcpRendD3D->GetRCamera().Orig), 1.f );
              sData[0].f[0] = vGridSpaceCamPos.x;
              sData[0].f[1] = vGridSpaceCamPos.y;
              sData[0].f[2] = vGridSpaceCamPos.z;
              sData[0].f[3] = vGridSpaceCamPos.w;
            }
          }
					break;
				}
			case ECGP_PB_GIAttenuation:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
						if(pGIVolume)
						{
							const float d = pGIVolume->GetVisibleDistance() * .5f;
							const float offset = min(d * .5f, 20.f);
							// att(d) = kd+b;
							const float k = -1.f / offset;
							const float b = d / offset;
							float fGIAmount = pGIVolume->GetIntensity() * gEnv->p3DEngine->GetGIAmount();
							// Apply LBuffers range rescale
							fGIAmount *= gcpRendD3D->m_fAdaptedSceneScaleLBuffer;
							const Vec4 vAttenuation(k, b, fGIAmount, CRenderer::CV_r_useparticles_giamount);
							sData[0].f[0] = vAttenuation.x;
							sData[0].f[1] = vAttenuation.y;
							sData[0].f[2] = vAttenuation.z;
							sData[0].f[3] = vAttenuation.w;
						}
					}
					break;
				}
			case ECGP_PB_GIGridCenter:
				{
					if(LPVManager.IsGIRenderable())
					{
						CRELightPropagationVolume* pGIVolume = LPVManager.GetCurrentGIVolume();
            if(pGIVolume)
            {
              const Vec3 gridCenter = pGIVolume->GetRenderSettings().m_matInv.TransformPoint(Vec3(.5f, .5f, .5f));
              Vec4 vGridCenter(gridCenter, 0);
              sData[0].f[0] = vGridCenter.x;
              sData[0].f[1] = vGridCenter.y;
              sData[0].f[2] = vGridCenter.z;
              sData[0].f[3] = vGridCenter.w;
            }
          }
					break;
				}				

      case 0:
        break;

      default:
        assert(0);
        break;
        //Warning("Unknown Parameter '%s' of type %d", ParamBind->m_Name.c_str(), ParamBind->m_eCGParamType);
        //assert(0);
        //return NULL;
      }
      if (ParamBind->m_Flags & PF_SINGLE_COMP)
        break;

			paramType >>= 8;
    }
    if (pSrc)
    {
      // in WIN32 pData must be 16 bytes aligned
      assert(!((uint32)pSrc & 0xf) || sizeof(void *)!=4);
#if !defined (DIRECT3D10)



      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH);
      else
        mfParameteri(ParamBind, pSrc, eSH);

#else
      if (!(ParamBind->m_Flags & PF_INTEGER))
        mfParameterfA(ParamBind, pSrc, nParams, eSH, nMaxVecs);
      else
        mfParameteri(ParamBind, pSrc, eSH, nMaxVecs);
#endif
    }
    ++ParamBind;
  }
}


//=========================================================================================

void CHWShader_D3D::mfReset(uint32 CRC32)
{
  for (uint32 i=0; i<m_Insts.size(); i++)
  {
    m_pCurInst = &m_Insts[i];
    if (!m_pCurInst->m_bDeleted)
      m_pCurInst->Release(m_pDevCache);
  }
  m_pCurInst = NULL;
	m_Insts.clear();
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
	m_LookupMap.clear();
#endif
  if (CRC32!=0 && gRenDev->m_cEF.m_nCombinationsProcess < 0)
  {
    // Delete all shared instances for this shader
    InstanceMapItor itInst = m_SharedInsts.find(m_EntryFunc);
    SHWSSharedList *pInstSH = NULL;
    if (itInst != m_SharedInsts.end())
    {
      pInstSH = itInst->second;
      uint32 i, j;
      const char *nm = gRenDev->m_RP.m_pShader->m_NameShader.c_str();
      SHWSSharedName *pSHN;
      for (i=0; i<pInstSH->m_SharedNames.size(); i++)
      {
        pSHN = &pInstSH->m_SharedNames[i];
        if (!stricmp(pSHN->m_Name.c_str(), nm))
          break;
      }
      if (i != pInstSH->m_SharedNames.size())
      {
        if (pSHN->m_CRC32 != CRC32)
        {
          pSHN->m_CRC32 = CRC32;
          for (i=0; i<pInstSH->m_SharedInsts.size(); i++)
          {
            SHWSSharedInstance *pSHI = &pInstSH->m_SharedInsts[i];
            for (j=0; j<pSHI->m_Insts.size(); j++)
            {
              m_pCurInst = &pSHI->m_Insts[j];
              m_pCurInst->Release(m_pDevCache);
            }
						pSHI->m_Insts.clear();
						m_pCurInst = 0;
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
						pSHI->m_LookupMap.clear();
#endif
          }
          pInstSH->m_SharedInsts.clear();
        }
      }
      else
      {
        int nnn = 0;
      }
    }
  }

  mfCloseCacheFile();
}

CHWShader_D3D::~CHWShader_D3D()
{
  mfFree(0);
}

static bool sCanSet(const STexSamplerRT *pSM, CTexture *pTex)
{
  assert(pTex);
  if (!pTex)
    return false;
  if (!pSM->m_bGlobal)
    return true;
  CD3D9Renderer *pRD = gcpRendD3D;
  if (pRD->m_pNewTarget[0] && pRD->m_pNewTarget[0]->m_pTex == pTex)
    return false;
  if (pRD->m_pNewTarget[1] && pRD->m_pNewTarget[1]->m_pTex == pTex)
    return false;
  return true;
}
static CTexture *sDefaultMaterialTexture(int nTexMaterialSlot, SRenderShaderResources *pSR)
{
  CTexture *tx = CTexture::s_ptexNoTexture;           

  if (nTexMaterialSlot)
  {
    // if no texture, pass dummy textures (to minimize shader permutations)
    tx = CTexture::s_ptexWhite;
    if (nTexMaterialSlot == EFTT_DECAL_OVERLAY )
      tx = CTexture::s_ptexGray;
    else
    if (nTexMaterialSlot == EFTT_BUMP)
      tx = CTexture::s_ptexFlatBump;
    else
    if (nTexMaterialSlot == EFTT_BUMP_DIFFUSE)
    {
      if (pSR && pSR->m_Textures[EFTT_BUMP]) 
        tx = pSR->m_Textures[EFTT_BUMP]->m_Sampler.m_pTex;
      else
        tx = CTexture::s_ptexFlatBump;
    }
  }
  return tx;
}

bool CHWShader_D3D::mfSetSamplers(const std::vector<STexSamplerRT>& Samplers, EHWShaderClass eSHClass)
{
	FUNCTION_PROFILER_RENDER_FLAT
  //PROFILE_FRAME(Shader_SetShaderSamplers);
  const uint32 nSize = Samplers.size();
  if (!nSize)
    return true;
  CD3D9Renderer *__restrict rd = gcpRendD3D;
  SRenderShaderResources *__restrict pSR = rd->m_RP.m_pShaderResources;

  uint32 i;
  const STexSamplerRT *pSamp = &Samplers[0];
	// Loop counter increments moved to resolve an issue where the compiler introduced
	// load hit stores by storing the counters as the last instruction in the loop then
	// immediated reloading and incrementing them after the branch back to the top
  for (i=0; i<nSize; /*i++, pSamp++*/)
  {
    CTexture *tx = pSamp->m_pTex;
    assert(tx);
    if (!tx)
		{
			++pSamp;
			++i;
      continue;
		}
    //int nSetID = -1;
    int nTexMaterialSlot = -1;
    const STexSamplerRT *pSM = pSamp++;
    int nSUnit = pSM->m_nSamplerSlot;
    int nTUnit = pSM->m_nTextureSlot;
    assert(nTUnit >= 0);
    int nTState = pSM->m_nTexState;
#ifndef _RELEASE
    ETEX_Type eShaderTT = (ETEX_Type)pSM->m_eTexType;
#endif
		++i;
    if (tx >= &CTexture::s_ShaderTemplates[0] && tx <= &CTexture::s_ShaderTemplates[EFTT_MAX-1])
    {
      nTexMaterialSlot = (int)(tx - &CTexture::s_ShaderTemplates[0]);

      if (!pSR || !pSR->m_Textures[nTexMaterialSlot])
        tx = sDefaultMaterialTexture(nTexMaterialSlot, pSR);
      else
      {
        pSM = &pSR->m_Textures[nTexMaterialSlot]->m_Sampler;
        tx = pSM->m_pTex;

        if (nTState<0 || !CTexture::s_TexStates[nTState].m_bActive)
          nTState = pSM->m_nTexState;   // Use material texture state

        IDynTextureSourceImpl* pDynTexSrc = (IDynTextureSourceImpl*) pSM->m_pDynTexSource;
        if (pDynTexSrc)
        {
          if (pDynTexSrc->Apply(nTUnit, nTState))
            continue;
          else
            tx = CTexture::s_ptexWhite;
        }
      }
    }
    if (pSM && pSM->m_pAnimInfo)
    {
      STexSamplerRT *pRT = (STexSamplerRT *)pSM;
      pRT->Update();
			tx = pRT->m_pTex;
    }
    if (!tx)
      continue;

    /*if (tx->IsNoTexture())
    {
      int nnn = 0;
    }*/
    {
      int nCustomID = tx->GetCustomID();
      if (nCustomID <= 0)
      {
				if (tx->UseDecalBorderCol())
				{
					STexState TS = CTexture::s_TexStates[nTState];
					//TS.SetFilterMode(...); // already set up
#if !defined(XENON)
					TS.SetClampMode(TADDR_BORDER, TADDR_BORDER, TADDR_BORDER);
					TS.SetBorderColor(ColorF(1,1,1,0).pack_argb8888());


#endif
					nTState = CTexture::GetTexState(TS);
				}







        tx->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);
      }
      else
      switch (nCustomID)
      {
        case TO_FROMRE0:
        case TO_FROMRE1:
          {
            if (rd->m_RP.m_pRE)
              nCustomID = rd->m_RP.m_pRE->m_CustomTexBind[nCustomID-TO_FROMRE0];
            else
              nCustomID = rd->m_RP.m_RECustomTexBind[nCustomID-TO_FROMRE0];
            if (nCustomID < 0)
              break;

            CTexture *pTex = CTexture::GetByID(nCustomID);
            pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_ZTARGET_MS:
          {
            CTexture *pTex = CTexture::s_ptexZTarget;
            assert(pTex);
            if (pTex)
              pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, 4);
          }
          break;

        case TO_SCENE_NORMALMAP_MS:
        case TO_SCENE_NORMALMAP:
          {            
            CTexture *pTex = CTexture::s_ptexSceneNormalsMap;
            if (sCanSet(pSM, pTex))
            {
              if ( nCustomID != TO_SCENE_NORMALMAP_MS )
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1);
              else
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nTUnit, 4);
            }
          }
          break;
        case TO_SCENE_UVSMAP_MS:
        case TO_SCENE_UVSMAP:
          {
            CTexture *pTex = CTexture::s_ptexSceneUVsMap;
            if (sCanSet(pSM, pTex))
            {
              if ( nCustomID != TO_SCENE_UVSMAP_MS )
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1);
              else
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nTUnit, 4);
            }
          }
          break;

				case TO_SHADOWID0:
				case TO_SHADOWID1:
				case TO_SHADOWID2:
				case TO_SHADOWID3:
				case TO_SHADOWID4:
				case TO_SHADOWID5:
				case TO_SHADOWID6:
				case TO_SHADOWID7:
					{
						int nShadowMapNum = nCustomID;
						nCustomID = rd->m_RP.m_ShadowCustomTexBind[nCustomID-TO_SHADOWID0];

						if (nCustomID < 0)
							break;
						//force  MinFilter = Linear; MagFilter = Linear; for HW_PCF_FILTERING
						STexState TS = CTexture::s_TexStates[nTState];
						TS.m_pDeviceState = NULL;

#if defined (DIRECT3D10)
						SShaderProfile *pSP = &gRenDev->m_cEF.m_ShaderProfiles[eST_Shadow];
						int nShadowQuality = (int)pSP->GetShaderQuality();
						bool bShadowsVeryHigh = nShadowQuality == eSQ_VeryHigh;

						//TF reset custom res view after shadow pass
						int nCustomResViewID = rd->m_RP.m_ShadowCustomResViewID[nShadowMapNum-TO_SHADOWID0];
						if ((!bShadowsVeryHigh || nShadowMapNum!=TO_SHADOWID0) &&(gRenDev->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[ HWSR_HW_PCF_COMPARE ]))
						{
							TS.SetFilterMode(FILTER_LINEAR);
							if (nCustomResViewID>=0)
							{
								//texture array case
								TS.SetComparisonFilter(false);
							}
							else
							{
								//non texture array case
								TS.SetComparisonFilter(true);
								TS.SetClampMode(TADDR_CLAMP, TADDR_CLAMP, TADDR_CLAMP);
							}
						}
						else
						{
							if (gRenDev->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[ HWSR_SHADOW_FILTER ])
							{
								TS.SetFilterMode(FILTER_LINEAR);
								TS.SetComparisonFilter(false);
							}
							else
							{
								TS.SetFilterMode(FILTER_POINT);
								TS.SetComparisonFilter(false);
							}
						}
#else
						if ((gRenDev->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[ HWSR_HW_PCF_COMPARE ]))
						{
							TS.SetFilterMode(FILTER_LINEAR);
						}
						else
						{
							//nCustomID = rd->m_RP.m_ShadowCustomTexBind[TO_SHADOWID0];
							if (gRenDev->m_RP.m_FlagsShader_RT & g_HWSR_MaskBit[ HWSR_SHADOW_FILTER ])
							{
								TS.SetFilterMode(FILTER_LINEAR);
							}
							else
							{
								TS.SetFilterMode(FILTER_POINT);
							}
						}
#endif

						//TS.PostCreate();

						CTexture* tex  = CTexture::GetByID(nCustomID);
#if defined(DIRECT3D10)
						tex->Apply(nTUnit, CTexture::GetTexState(TS), nTexMaterialSlot, nSUnit, nCustomResViewID);
#else
						tex->Apply(nTUnit, CTexture::GetTexState(TS), nTexMaterialSlot, nSUnit);
#endif
					}
					break;

				case TO_FROMRE0_FROM_CONTAINER:
        case TO_FROMRE1_FROM_CONTAINER:
          {
            // take render element from vertex container render mesh if available
            CRendElementBase *pRE = sGetContainerRE0(rd->m_RP.m_pRE);
            if (pRE)
              nCustomID = pRE->m_CustomTexBind[nCustomID-TO_FROMRE0_FROM_CONTAINER];
            else
              nCustomID = rd->m_RP.m_RECustomTexBind[nCustomID-TO_FROMRE0_FROM_CONTAINER];
            if (nCustomID < 0)
              break;
            CTexture::ApplyForID(nTUnit, nCustomID, nTState, nSUnit);
          }
          break;

        case TO_SCREENSHADOWMAP:
          {
            CTexture *tex = NULL;
            int nCurLightGroup = rd->m_RP.m_nCurLightGroup;
            if (rd->m_RP.m_PersFlags2 & RBPF2_RAINPASS) // special case for rain pass - make sure light group is 0
              nCurLightGroup = 0;

						uint32 passGroupId = rd->m_RP.m_nPassGroupID;
						if (passGroupId ==  EFSLIST_TRANSP)
						  nCurLightGroup = -1;
						
            if (nCurLightGroup >= 0)
            {
              int nGroup = nCurLightGroup>=0 ? nCurLightGroup : MAX_REND_LIGHT_GROUPS;
#ifndef _RELEASE
              if (SRendItem::m_RecurseLevel[rd->m_RP.m_nProcessThreadID]==0) __debugbreak();
#endif 
              if (SRendItem::m_ShadowsValidMask[SRendItem::m_RecurseLevel[rd->m_RP.m_nProcessThreadID]-1][nGroup])
              {
                assert(nCurLightGroup>=0 && nCurLightGroup<MAX_REND_LIGHTS/4);
                tex  = CTexture::s_ptexCurrentScreenShadowMap[nCurLightGroup];
              }
              else
                tex = CTexture::s_ptexBlack;
            }
            else
              tex = CTexture::s_ptexBlack;
            assert(tex);
            if (tex)
              tex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_DEFERDECALS_RT:
          {
            CTexture *tex = NULL;
            if ( rd->CV_r_deferredDecals>=3 && rd->m_bDeferredDecals)
            {
              if (CTexture::s_ptexDeferredDecalTarget->GetDevTexture()!=NULL &&
                  CTexture::s_ptexDeferredDecalTarget->m_nUpdateFrameID==rd->GetFrameID(false)
									&& !(rd->m_RP.m_pCurObject->m_ObjFlags & FOB_NO_STATIC_DECALS))
              {
                tex = CTexture::s_ptexDeferredDecalTarget;
              }
              else
                tex = CTexture::s_ptexBlackAlpha;
            }
            else
              tex = CTexture::s_ptexBlackAlpha;
            if (sCanSet(pSM, tex))
              tex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

				case TO_SCATTER_LAYER:
					{
						CTexture *tex = NULL;




						if ( CTexture::s_ptexScatterLayer )
							tex = CTexture::s_ptexScatterLayer;

						else
						{
							tex = CTexture::s_ptexBlack;
						}

						assert(tex);
						if (tex)
							tex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					}
					break;

        case TO_SCENE_DIFFUSE_ACC_MS:
        case TO_SCENE_DIFFUSE_ACC:
          {
            const uint32 nLightsCount = CDeferredShading::Instance().GetLightsCount();
            CTexture *pTex = nLightsCount? CTexture::s_ptexCurrentSceneDiffuseAccMap: CTexture::s_ptexBlack;
            if (sCanSet(pSM, pTex))
            {              
              if ( !(nLightsCount && nCustomID == TO_SCENE_DIFFUSE_ACC_MS) )
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1);
              else
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nTUnit, 4);
            }
          }
          break;

        case TO_SCENE_SPECULAR_ACC_MS:
        case TO_SCENE_SPECULAR_ACC:
          {
            const uint32 nLightsCount = CDeferredShading::Instance().GetLightsCount();
            CTexture *pTex = nLightsCount? CTexture::s_ptexSceneSpecularAccMap : CTexture::s_ptexBlack;
            if (sCanSet(pSM, pTex))
            {
              if ( !(nLightsCount && nCustomID == TO_SCENE_SPECULAR_ACC_MS) )
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1);
              else
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nTUnit, 4);
            }
          }
          break;

        case TO_SCENE_TARGET:
          {
            CTexture *tex = CTexture::s_ptexCurrSceneTarget;
            if( !tex )
              tex = CTexture::s_ptexWhite;

            tex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_DOWNSCALED_ZTARGET_FOR_AO:
          {
            assert(CTexture::s_ptexZTargetScaled);
            if (CTexture::s_ptexZTargetScaled)
              CTexture::s_ptexZTargetScaled->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_QUARTER_ZTARGET_FOR_AO:
          {
            assert(CTexture::s_ptexZTargetScaled2);
            if (CTexture::s_ptexZTargetScaled2)
              CTexture::s_ptexZTargetScaled2->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

				case TO_FROMOBJ:
					{
						CTexture *pTex = CTexture::s_ptexBlack;
						if (rd->m_RP.m_pCurObject)
						{
							nCustomID = rd->m_RP.m_pCurObject->m_nTextureID;
							if (nCustomID > 0)
								pTex = CTexture::GetByID(nCustomID);
						}
						pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					}
					break;

				case TO_FROMOBJ_CM:
					{
						CTexture *pTex = CTexture::s_ptexNoTextureCM;
						if (rd->m_RP.m_pCurObject)
						{
							nCustomID = rd->m_RP.m_pCurObject->m_nTextureID;
							if (nCustomID > 0)
								pTex = CTexture::GetByID(nCustomID);
							else if (nCustomID == 0)
								pTex = CTexture::s_ptexBlackCM;
						}
						pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					}
					break;

        case TO_FROMLIGHT:
          {
            bool bRes = CTexture::SetProjector(nTUnit, nTState, nSUnit);
            if (!bRes && !(rd->m_RP.m_PersFlags1 & RBPF1_MULTILIGHTS))
							Warning( "Couldn't set projected texture for light source (Shader: '%s')\n", rd->m_RP.m_pShader ? rd->m_RP.m_pShader->GetName() : "null" );
          }
          break;

        case TO_RT_CM:
          {
            SHRenderTarget *pRT = pSM->m_pTarget ? pSM->m_pTarget : pSamp->m_pTarget;
            assert(pRT);
            if (!pRT)
              break;
            SEnvTexture *pEnvTex = pRT->GetEnvCM();
            assert(pEnvTex->m_pTex);
            if (pEnvTex && pEnvTex->m_pTex)
              pEnvTex->m_pTex->Apply(nTUnit, nTState);
          }
          break;

        case TO_RT_2D:
          {
            SHRenderTarget *pRT = pSM->m_pTarget ? pSM->m_pTarget : pSamp->m_pTarget;
            SEnvTexture *pEnvTex = pRT->GetEnv2D();
            //assert(pEnvTex->m_pTex);
            if (pEnvTex && pEnvTex->m_pTex)
              pEnvTex->m_pTex->Apply(nTUnit, nTState);
          }
          break;

        case TO_WATEROCEANMAP:
            CTexture::s_ptexWaterOcean->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);
          break;

        case TO_WATERVOLUMEMAP:
          {
            if( CTexture::s_ptexWaterVolumeDDN )
            {
              CEffectParam *pParam = PostEffectMgr()->GetByName("WaterVolume_Amount"); 
              assert(pParam && "Parameter doesn't exist");

              // Activate puddle generation
              if (pParam)
                pParam->SetParam(1.0f);   

              CTexture::s_ptexWaterVolumeDDN->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);
            }
            else
              CTexture::s_ptexFlatBump->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);

          }
          break;

        case TO_WATERRIPPLESMAP:
          {			
            if( CTexture::s_ptexWaterRipplesDDN )
				CTexture::s_ptexWaterRipplesDDN->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);
            else
              CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit, -1, eSHClass);
          }
          break;

        case TO_TERRAIN_LM:
          {
						const bool setupTerrainShadows = rd->m_bShadowsEnabled;
						if (setupTerrainShadows)
						{
							// terrain shadow map
							ITerrain* pTerrain( gEnv->p3DEngine->GetITerrain() );
							Vec4 texGenInfo;
							int terrainLightMapID( pTerrain->GetTerrainLightmapTexId( texGenInfo ) );
							CTexture* pTerrainLightMap( terrainLightMapID > 0 ? CTexture::GetByID( terrainLightMapID ) : CTexture::s_ptexWhite );
							assert( pTerrainLightMap );

							STexState pTexStateLinearClamp;
							pTexStateLinearClamp.SetFilterMode(FILTER_LINEAR);        
							pTexStateLinearClamp.SetClampMode(true, true, true);
							int nTexStateLinearClampID = CTexture::GetTexState( pTexStateLinearClamp );

							pTerrainLightMap->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
						}
						else
						{
							CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
						}

						break;
          }

        case TO_BACKBUFFERSCALED_D2:
          CTexture::s_ptexBackBufferScaled[0]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          break;
        case TO_BACKBUFFERSCALED_D4:
          CTexture::s_ptexBackBufferScaled[1]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          break;
        case TO_BACKBUFFERSCALED_D8:
          CTexture::s_ptexBackBufferScaled[2]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          break;
				case TO_BACKBUFFERSCALED_D16:
					CTexture::s_ptexBackBufferScaled[3]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;

        case TO_CLOUDS_LM:
          {
            const bool setupCloudShadows = rd->m_bShadowsEnabled && rd->m_bCloudShadowsEnabled;
            if (setupCloudShadows)
            {
              // cloud shadow map 
              CTexture* pCloudShadowTex( rd->GetCloudShadowTextureId() > 0 ? CTexture::GetByID( rd->GetCloudShadowTextureId() ) : CTexture::s_ptexWhite );
              assert( pCloudShadowTex );

              STexState pTexStateLinearClamp;
              pTexStateLinearClamp.SetFilterMode(FILTER_LINEAR);        
              pTexStateLinearClamp.SetClampMode(false, false, false);
              int nTexStateLinearClampID = CTexture::GetTexState( pTexStateLinearClamp );

              pCloudShadowTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
            }
            else
            {
              CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
            }

            break;
          }

        case TO_MIPCOLORS_DIFFUSE:
          {
            CTexture *pTex = NULL;
            if (pSR && pSR->m_Textures[EFTT_DIFFUSE])
            {
              CTexture *tex = pSR->m_Textures[EFTT_DIFFUSE]->m_Sampler.m_pTex;
              pTex = CTexture::GenerateMipsColorMap(tex->GetWidth(), tex->GetHeight());
              if (pTex)
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
            }
            if (!pTex)
              CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_MIPCOLORS_BUMP:
          {
            CTexture *pTex = NULL;
            if (pSR && pSR->m_Textures[EFTT_BUMP])
            {
              CTexture *tex = pSR->m_Textures[EFTT_BUMP]->m_Sampler.m_pTex;
              pTex = CTexture::GenerateMipsColorMap(tex->GetWidth(), tex->GetHeight());
              if (pTex)
                pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
            }
            if (!pTex)
              CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
          }
          break;

        case TO_BACKBUFFERMAP:        
					{
						CTexture *pBackBufferTex = PostProcessUtils().GetBackBufferTexture();
						if( pBackBufferTex )
							pBackBufferTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);    

						//CTexture::s_ptexBackBuffer->Apply(-1, nTS);    

					}
          break;
        case TO_HDRTARGET_ENCODED:






          break;

#ifndef EXCLUDE_SCALEFORM_SDK
        case TO_FROMSF0:
        case TO_FROMSF1:
				case TO_FROMSFY:
				case TO_FROMSFU:
				case TO_FROMSFV:
				case TO_FROMSFA:
          {
            const SSF_GlobalDrawParams* pParams = rd->SF_GetGlobalDrawParams();
            assert(pParams);
            if (pParams)
						{
							int texIdx = nCustomID - TO_FROMSF0;
							int texID = -1;

							if (texIdx < 2)
							{
								texID = pParams->texture[texIdx].texID;
							}
							else
							{
								assert(texIdx < 6);
								texID = pParams->texID_YUVA[texIdx-2];
								texIdx = 0;
							}

							if (texID > 0)
							{
								const static int texStateID[8] = 
								{
									CTexture::GetTexState(STexState(FILTER_POINT, false)), CTexture::GetTexState(STexState(FILTER_POINT, true)),
									CTexture::GetTexState(STexState(FILTER_LINEAR, false)), CTexture::GetTexState(STexState(FILTER_LINEAR, true)),
									CTexture::GetTexState(STexState(FILTER_TRILINEAR, false)), CTexture::GetTexState(STexState(FILTER_TRILINEAR, true)),
									-1, -1
								};
								CTexture* pTex = CTexture::GetByID(texID);
								int textStateID = texStateID[pParams->texture[texIdx].texState];
								pTex->Apply(nTUnit, textStateID);
								break;
							}
						}
						CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
            break;
          }
#endif

			case TO_VOLOBJ_DENSITY:
			case TO_VOLOBJ_SHADOW:
				{
					bool texBound(false);
					CRendElementBase* pRE(rd->m_RP.m_pRE);
					if (pRE && pRE->mfGetType() == eDATA_VolumeObject)
					{
						CREVolumeObject* pVolObj((CREVolumeObject*)pRE);
						int texId(0);
						if (pVolObj)
						{
							switch(nCustomID)
							{
							case TO_VOLOBJ_DENSITY:
								if (pVolObj->m_pDensVol)
									texId = pVolObj->m_pDensVol->GetTexID();
								break;
							case TO_VOLOBJ_SHADOW:
								if (pVolObj->m_pShadVol)
									texId = pVolObj->m_pShadVol->GetTexID();
								break;
							default:
								assert(0);
								break;
							}
						}
						CTexture* pTex(texId > 0 ? CTexture::GetByID(texId) : 0);
						if (pTex)
						{
							pTex->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
							texBound = true;
						}
					}
					if (!texBound)
						CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;
				}

			case TO_COLORCHART:
				{
					CColorGradingControllerD3D* pCtrl = gcpRendD3D->m_pColorGradingControllerD3D;
					if (pCtrl)
					{
						CTexture* pTex = pCtrl->GetColorChart();
						if (pTex)
						{
							const static int texStateID = CTexture::GetTexState(STexState(FILTER_LINEAR, true));
							pTex->Apply(nTUnit, texStateID);
							break;
						}
					}
          CRenderer::CV_r_colorgrading_charts = 0;
					CTexture::s_ptexWhite->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;
				}

			case TO_SKYDOME_MIE:
			case TO_SKYDOME_RAYLEIGH:
				{
					CRendElementBase* pRE = rd->m_RP.m_pRE;
					if (pRE && pRE->mfGetType() == eDATA_HDRSky)
					{
						CTexture* pTex = nCustomID == TO_SKYDOME_MIE ? ((CREHDRSky*) pRE)->m_pSkyDomeTextureMie : ((CREHDRSky*) pRE)->m_pSkyDomeTextureRayleigh;
						if (pTex)
						{
							pTex->Apply(nTUnit, -1, nTexMaterialSlot, nSUnit);
							break;
						}
					}
					CTexture::s_ptexBlack->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;
				}

			case TO_SKYDOME_MOON:
				{
					CRendElementBase* pRE = rd->m_RP.m_pRE;
					if (pRE && pRE->mfGetType() == eDATA_HDRSky)
					{
						CREHDRSky* pHDRSky = (CREHDRSky*) pRE;
						CTexture* pMoonTex(pHDRSky->m_moonTexId > 0 ? CTexture::GetByID(pHDRSky->m_moonTexId) : 0);
						if (pMoonTex)
						{
							const static int texStateID = CTexture::GetTexState(STexState(FILTER_BILINEAR, true));
							pMoonTex->Apply(nTUnit, texStateID);
							break;
						}
					}
					CTexture::s_ptexBlack->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;
				}

			case TO_VOLFOGSHADOW_BUF:
				{
#if defined(VOLUMETRIC_FOG_SHADOWS)
					const bool enabled = gRenDev->m_bVolFogShadowsEnabled;
					assert(enabled);
					CTexture* pTex = enabled ? CTexture::s_ptexVolFogShadowBuf[0] : CTexture::s_ptexWhite;
					pTex ->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
					break;
#else
					assert(0);
					break;
#endif
				}

			case TO_LPV_R:
				if(CTexture::s_ptexLPV_RTs[0])
					CTexture::s_ptexLPV_RTs[0]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
				break;
			case TO_LPV_G:
				if(CTexture::s_ptexLPV_RTs[1])
					CTexture::s_ptexLPV_RTs[1]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
				break;
			case TO_LPV_B:
				if(CTexture::s_ptexLPV_RTs[2])
					CTexture::s_ptexLPV_RTs[2]->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);    
				break;
			case TO_RSM_NORMAL:
				if(CTexture::s_ptexRSMNormals)
					CTexture::s_ptexRSMNormals->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);    
				break;
			case TO_RSM_COLOR:
				if(CTexture::s_ptexRSMFlux)
					CTexture::s_ptexRSMFlux->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);    
				break;
			case TO_RSM_DEPTH:
				if(CTexture::s_ptexRSMDepth)
					CTexture::s_ptexRSMDepth->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);    
        break;
      default:
        {
          tx->Apply(nTUnit, nTState, nTexMaterialSlot, nSUnit);
        }
        break;
      }
    }
  }

  return true;
}

bool CHWShader_D3D::mfUpdateSamplers()
{
	FUNCTION_PROFILER_RENDER_FLAT
  if (!m_pCurInst)
    return false;
  SHWSInstance *pInst = m_pCurInst;
  if (!pInst->m_pSamplers.size())
    return true;

  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];
  
  STexSamplerRT *pSamp = &pInst->m_pSamplers[0];

  SRenderShaderResources *pSR = gRenDev->m_RP.m_pShaderResources;	

  uint32 i;
  const uint32 nSize = pInst->m_pSamplers.size();
  bool bDiffuseSlotUpdated = false;
	
  for (i=0; i<nSize; i++, pSamp++)
  {
    CTexture *tx = pSamp->m_pTex;
    //assert(tx);
    if (!tx)
      continue;
    if (tx >= &CTexture::s_ShaderTemplates[0] && tx <= &CTexture::s_ShaderTemplates[EFTT_MAX-1])
    {
      {
        int nSlot = (int)(tx - &CTexture::s_ShaderTemplates[0]);
        if (pSR && pSR->m_Textures[nSlot])
        {



					if( nSlot != EFTT_DETAIL_OVERLAY )
						pSR->m_Textures[nSlot]->Update(nSlot);

					if (nSlot == EFTT_BUMP_HEIGHT)
					{
						SEfResTexture* pBumpTexSlot = pSR->m_Textures[EFTT_BUMP];
						if (pBumpTexSlot)
							pBumpTexSlot->Update(EFTT_BUMP);
					}
					else
          if( nSlot == EFTT_DIFFUSE ) 
            bDiffuseSlotUpdated = true;
          
          if ( (rTI.m_PersFlags & RBPF_ZPASS) && nSlot == EFTT_BUMP && pSR && !bDiffuseSlotUpdated) 
          {



            if (pSR->m_Textures[EFTT_DIFFUSE] )
              pSR->m_Textures[EFTT_DIFFUSE]->Update(EFTT_DIFFUSE);
          }

          tx = pSR->m_Textures[nSlot]->m_Sampler.m_pTex;
        }
        else
        {
          if (nSlot == EFTT_BUMP)
            tx = CTexture::s_ptexFlatBump;
        }
      }
    }
  }

  return true;
}

void CHWShader_D3D::mfInit()
{
	CGParamManager::Init();
}

ED3DShError CHWShader_D3D::mfFallBack(SHWSInstance *&pInst, int nStatus)
{
  // No fallback for:
  // 1. ShadowGen pass
  // 2. Z-prepass
  // 3. Glow-pass
  // 4. Shadow-pass
#if defined (DIRECT3D10) || defined (DIRECT3D9) && !defined(XENON) && !defined(PS3)
  if (CParserBin::m_nPlatform & (SF_PS3 | SF_XENON | SF_D3D11 | SF_D3D10))
  {
    //assert(gRenDev->m_cEF.m_nCombinationsProcess >= 0);
    return ED3DShError_CompilingError;
  }
#endif



  if (
#if !defined(XENON) && !defined(PS3) && !defined(CAFE) 
    m_eSHClass == eHWSC_Geometry || m_eSHClass == eHWSC_Domain || m_eSHClass == eHWSC_Hull ||
#endif
    (gRenDev->m_RP.m_nBatchFilter & (FB_Z | FB_GLOW | FB_SCATTER)) || (gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN) || gRenDev->m_RP.m_nPassGroupID == EFSLIST_SHADOW_PASS)
    return ED3DShError_CompilingError;
  if (gRenDev->m_RP.m_pShader)
  {
    if (gRenDev->m_RP.m_pShader->GetShaderType() == eST_HDR || gRenDev->m_RP.m_pShader->GetShaderType() == eST_PostProcess || gRenDev->m_RP.m_pShader->GetShaderType() == eST_Water || gRenDev->m_RP.m_pShader->GetShaderType() == eST_Shadow || gRenDev->m_RP.m_pShader->GetShaderType() == eST_Shadow)
      return ED3DShError_CompilingError;
  }
  // Skip rendering if async compiling Cvar is 2
  if (CRenderer::CV_r_shadersasynccompiling == 2)
    return ED3DShError_CompilingError;

  CShader *pSH = CShaderMan::m_ShaderFallback;
  int nTech = 0;
  if (nStatus == -1)
  {
    pInst->m_Handle.m_bStatus = 1;
    nTech = 1;
  }
  else
  {
    nTech = 0;
    assert(nStatus == 0);
  }
  if (gRenDev->m_RP.m_pShader && gRenDev->m_RP.m_pShader->GetShaderType() == eST_Terrain)
    nTech += 2;

  assert(pSH);
  if (CRenderer::CV_r_logShaders)
  {
    char nameSrc[256];
    mfGetDstFileName(pInst, this, nameSrc, 256, 3);
    gcpRendD3D->LogShv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "Async %d: using Fallback tech '%s' instead of 0x%x '%s' shader\n", gRenDev->GetFrameID(false), pSH->m_HWTechniques[nTech]->m_NameStr.c_str(), pInst, nameSrc);
  }
  // Fallback
  if (pSH)
  {
    if (gRenDev->m_RP.m_CurState & GS_DEPTHFUNC_EQUAL)
    {
      int nState = gRenDev->m_RP.m_CurState & ~GS_DEPTHFUNC_EQUAL;
      nState |= GS_DEPTHWRITE;
      gRenDev->FX_SetState(nState);
    }
    CHWShader_D3D *pHWSH;
    if (m_eSHClass == eHWSC_Vertex)
    {
      pHWSH = (CHWShader_D3D *)pSH->m_HWTechniques[nTech]->m_Passes[0].m_VShader;
#ifdef DO_RENDERLOG
      if (CRenderer::CV_r_log >= 3)
        gcpRendD3D->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "---- Fallback FX VShader \"%s\"\n", pHWSH->GetName());
#endif
    }
    else
    {
      pHWSH = (CHWShader_D3D *)pSH->m_HWTechniques[nTech]->m_Passes[0].m_PShader;
#ifdef DO_RENDERLOG
      if (CRenderer::CV_r_log >= 3)
        gcpRendD3D->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "---- Fallback FX PShader \"%s\"\n", pHWSH->GetName());
#endif
    }

    if (!pHWSH->m_Insts.size())
    {
      SShaderCombination cmb;
      pHWSH->mfPrecache(cmb, true, true, false, gRenDev->m_RP.m_pShader, gRenDev->m_RP.m_pShaderResources);
    }
    if (pHWSH->m_Insts.size())
    {
      SHWSInstance *pInstF = &pHWSH->m_Insts[0];
      if (!pInstF->m_Handle.m_pShader || !pInstF->m_Handle.m_pShader->m_pHandle)
        return ED3DShError_CompilingError;
      pInst = pInstF;
      m_pCurInst = pInstF;
      pInstF->m_bFallback = true;
    }
    else
      return ED3DShError_CompilingError;
  }
  //if (nStatus == 0)
  //  return ED3DShError_Compiling;
  return ED3DShError_Ok;

}

ED3DShError CHWShader_D3D::mfIsValid_Int(SHWSInstance *&pInst, bool bFinalise)
{
  //if (stricmp(m_EntryFunc.c_str(), "FPPS") && stricmp(m_EntryFunc.c_str(), "FPVS") && stricmp(m_EntryFunc.c_str(), "AuxGeomPS") && stricmp(m_EntryFunc.c_str(), "AuxGeomVS"))
  //  return mfFallBack(pInst, 0);

  if (pInst->m_Handle.m_bStatus == 1)
  {
    return mfFallBack(pInst, -1);
  }
  if (pInst->m_Handle.m_bStatus == 2)
    return ED3DShError_Fake;
  if (pInst->m_Handle.m_pShader == NULL)
  {
    if (pInst->m_bAsyncActivating)
      return mfFallBack(pInst, 0);
#if defined (WIN32) || defined(XENON)
    if (!bFinalise || !pInst->m_pAsync)
      return ED3DShError_NotCompiled;
    int nStatus = 0;
    if (!pInst->m_bAsyncActivating)
    {
      nStatus = mfAsyncCompileReady(pInst);
      if (nStatus == 1)
      {
        if (gcpRendD3D->m_cEF.m_nCombinationsProcess<=0 || gcpRendD3D->m_cEF.m_bActivatePhase)
        {
          assert(pInst->m_Handle.m_pShader != NULL);
        }
        return ED3DShError_Ok;
      }
    }
    return mfFallBack(pInst, nStatus);
#else
    return ED3DShError_NotCompiled;
#endif
  }
  return ED3DShError_Ok;
}

//========================================================================================

void CHWShader::mfBeginFrame(int nMaxToFlush)
{
#if !defined (XENON) && defined (WIN32)
  //CHWShader_D3D::mfFlushPendedShaders(nMaxToFlush);
#endif
}

void CHWShader::mfLazyUnload()
{
  int nScanned = 0;
  int nUnloaded = 0;
  static int nLastScannedPS = 0;
  static int nLastScannedVS = 0;
  static int sbReset = 0;
  if (!gRenDev->m_bEndLevelLoading)
  {
    sbReset = 0;
    nLastScannedPS = 0;
    nLastScannedVS = 0;
    return;
  }

  AUTO_LOCK(CBaseResource::s_cResLock);

  CCryNameTSCRC Name = CHWShader::mfGetClassName(eHWSC_Pixel);
  SResourceContainer *pRL = CBaseResource::GetResourcesForClass(Name);
  uint32 i;
	uint32 j;
  float fTime = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_RealTime;

  float fThr = (float)CRenderer::CV_r_shaderslazyunload;
  if (pRL)
  {
    for (i=nLastScannedPS; i<pRL->m_RList.size(); i++)
    {
      CHWShader_D3D *pPS = (CHWShader_D3D *)pRL->m_RList[i];
      int nDeleted = 0;
      for (j=0; j<pPS->m_Insts.size(); j++)
      {
        CHWShader_D3D::SHWSInstance *pInst = &pPS->m_Insts[j];
        if (pInst->m_bDeleted)
          continue;
        if (pInst->m_pAsync)
          continue;
        if (sbReset != 3)
          pInst->m_fLastAccess = fTime;
        else
        if (fTime-pInst->m_fLastAccess > fThr)
        {
          pPS->m_pCurInst = pInst;
          pInst->Release(pPS->m_pDevCache, false);
          pInst->m_bDeleted = true;
          nDeleted++;
          nUnloaded++;
          pPS->m_pCurInst = NULL;
        }
      }
      //if (nDeleted == pPS->m_Insts.size())
      //  pPS->mfReset(0);
      nScanned++;
      if (nUnloaded > 16)
        break;
      if (nScanned > 32)
        break;
    }
    if (i >= pRL->m_RList.size())
    {
      sbReset |= 1;
      i = 0;
    }
    nLastScannedPS = i;
  }
  Name = CHWShader::mfGetClassName(eHWSC_Vertex);
  pRL = CBaseResource::GetResourcesForClass(Name);
  nUnloaded = 0;
  nScanned = 0;
  if (pRL)
  {
    for (i=nLastScannedVS; i<pRL->m_RList.size(); i++)
    {
      CHWShader_D3D *pVS = (CHWShader_D3D *)pRL->m_RList[i];
      int nDeleted = 0;
      for (j=0; j<pVS->m_Insts.size(); j++)
      {
        CHWShader_D3D::SHWSInstance *pInst = &pVS->m_Insts[j];
        if (pInst->m_bDeleted)
          continue;
        if (pInst->m_pAsync)
          continue;
        if (sbReset != 3)
          pInst->m_fLastAccess = fTime;
        else
        if (fTime-pInst->m_fLastAccess > CRenderer::CV_r_shaderslazyunload)
        {
          pVS->m_pCurInst = pInst;
          pInst->Release(pVS->m_pDevCache, false);
          pInst->m_bDeleted = true;
          nDeleted++;
          nUnloaded++;
          pVS->m_pCurInst = NULL;
        }
      }
      //if (nDeleted == pVS->m_Insts.size())
      //  pVS->mfReset(0);
      nScanned++;
      if (nUnloaded > 16)
        break;
      if (nScanned > 32)
        break;
    }
    if (i >= pRL->m_RList.size())
    {
      sbReset |= 2;
      i = 0;
    }
    nLastScannedVS = i;
  }
}

struct InstContainerByHash
{
  bool operator () (const CHWShader_D3D::SHWSInstance& left, const CHWShader_D3D::SHWSInstance& right)const
  {
    return left.m_Ident.m_nHash < right.m_Ident.m_nHash;
  }
  bool operator () (const uint32 left, const CHWShader_D3D::SHWSInstance& right)const
  {
    return left < right.m_Ident.m_nHash;
  }
  bool operator () (const CHWShader_D3D::SHWSInstance& left, uint32 right)const
  {
    return left.m_Ident.m_nHash < right;
  }
};


CHWShader_D3D::SHWSInstance *CHWShader_D3D::mfGetInstance(CShader *pSH, int nHashInstance, uint64 GLMask)
{
	FUNCTION_PROFILER_RENDER_FLAT
  std::vector<SHWSInstance> *pInstCont = &m_Insts;
  if (m_Flags & HWSG_SHARED)
  {
    pInstCont = mfGetSharedInstContainer(pSH, true, GLMask, false);
    assert(pInstCont);
  }
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
  if (m_bUseLookUpTable)
  {
    assert(nHashInstance < pInstCont->size());
    SHWSInstance *pInst = &(*pInstCont)[nHashInstance];
    return pInst;
  }
#endif
  InstContainerIt it = std::lower_bound(pInstCont->begin(), pInstCont->end(), nHashInstance, InstContainerByHash());
  assert (it != pInstCont->end() && nHashInstance == (*it).m_Ident.m_nHash);

  return &(*it);
}

CHWShader_D3D::SHWSInstance *CHWShader_D3D::mfGetInstance(CShader *pSH, SShaderCombIdent& Ident, uint32 nFlags)
{
	FUNCTION_PROFILER_RENDER_FLAT
	SHWSInstance *cgi = m_pCurInst;
	if ((m_Flags & HWSG_SHARED) && m_nInstFrame != m_nCurInstFrame)
	{
		m_nCurInstFrame = m_nInstFrame;
		cgi = NULL;
	}
	if (cgi && !cgi->m_bFallback)
	{
		assert(cgi->m_eClass < eHWSC_Num);

		const SShaderCombIdent& other = cgi->m_Ident;
		// other will have been through PostCreate, and so won't have the platform mask set anymore
		if ((Ident.m_MDVMask & ~SF_PLATFORM) == other.m_MDVMask && Ident.m_RTMask == other.m_RTMask && Ident.m_GLMask == other.m_GLMask && Ident.m_FastCompare1 == other.m_FastCompare1)
			return cgi;
	} 
	InstContainerByHash findByHash;
	InstContainer *pInstCont = &m_Insts;
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
	THWInstanceLookupMap *pInstMap = &m_LookupMap;
#endif
	if (m_Flags & HWSG_SHARED)
	{
		pInstCont = mfGetSharedInstContainer(pSH, true, Ident.m_GLMask, (nFlags & HWSF_PRECACHE_INST)!=0);
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
		if (m_bUseLookUpTable)
			pInstMap = mfGetSharedInstMap(pSH, true, Ident.m_GLMask, (nFlags & HWSF_PRECACHE_INST)!=0);
#endif
	}
	uint32 identHash = Ident.PostCreate();
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
	if (m_bUseLookUpTable)
	{
		uint64 uiKey = Ident.m_RTMask + Ident.m_GLMask + Ident.m_LightMask + Ident.m_MDMask + Ident.m_MDVMask;

		std::pair<THWInstanceLookupMap::iterator, THWInstanceLookupMap::iterator> itp = pInstMap->equal_range(uiKey);
		for (THWInstanceLookupMap::iterator it = itp.first; it != itp.second; ++it)
		{
			// use index redirection
			uint32 uiIndex = it->second;
			cgi = &(*pInstCont)[uiIndex];
			if (cgi->m_Ident.m_nHash == identHash)
			{
				m_pCurInst = cgi;
				return cgi;
			}
		}
		SHWSInstance ci;
		ci.m_nVertexFormat = 1;
		ci.m_nCache = -1;
		m_nInstFrame++;
		ci.m_Ident = Ident;
		ci.m_eClass = m_eSHClass;
		pInstCont->push_back(ci);
		uint32 uiIndex = pInstCont->size() - 1;
		cgi = &((*pInstCont)[uiIndex]);
		if (nFlags & HWSF_FAKE)
		{
			cgi->m_Handle.SetFake();
			//mfSetHWStartProfile(nFlags);
		}

		// only store index to object instead of pointer itself
		// else we have lots of issues with the internal resize 
		// functionality of the vector itself (does some strange
		// allocation stuff once above 20 000 members)
		pInstMap->insert(std::pair<uint64, uint32>(uiKey, uiIndex));			
	} else 
#endif
	{
		cgi = 0;

		//int nFree = -1;
		InstContainerIt it = std::lower_bound(pInstCont->begin(), pInstCont->end(), identHash, findByHash);
		if (it != pInstCont->end() && identHash == (*it).m_Ident.m_nHash)
		{
#ifdef _RELEASE
			cgi = &*it;
#else
			while (identHash == (*it).m_Ident.m_nHash)
			{
				const SShaderCombIdent& other = it->m_Ident;
				if ((Ident.m_MDVMask & ~SF_PLATFORM) == other.m_MDVMask && Ident.m_RTMask == other.m_RTMask 
					&& Ident.m_GLMask == other.m_GLMask && Ident.m_FastCompare1 == other.m_FastCompare1)
				{
					cgi = &*it; 
					break;
				}

				assert(false);
				iLog->Log("Error: ShaderIdent hash value not unique!");

				++it;
			}

			if (cgi == 0)
				--it;
#endif		
		}

		if (cgi == 0)
		{
			SHWSInstance ci;
			ci.m_nVertexFormat = 1;
			ci.m_nCache = -1;
			m_nInstFrame++;
			ci.m_Ident = Ident;
			ci.m_eClass = m_eSHClass;
			int i = (int) std::distance(pInstCont->begin(), it);
			pInstCont->insert(it, ci);
			cgi = &(*pInstCont)[i];
			if (nFlags & HWSF_FAKE)
			{
				cgi->m_Handle.SetFake();
				//mfSetHWStartProfile(nFlags);
			}
		}
	}
	m_pCurInst = cgi;
	return cgi;
}

//=================================================================================

void CHWShader_D3D::mfSetForOverdraw(SHWSInstance *pInst, uint32 nFlags, uint64& RTMask)
{
  if (mfIsValid(pInst, false) ==  ED3DShError_NotCompiled)
    mfActivate(gRenDev->m_RP.m_pShader, nFlags);
  RTMask |= g_HWSR_MaskBit[HWSR_DEBUG0] | g_HWSR_MaskBit[HWSR_DEBUG1] | g_HWSR_MaskBit[HWSR_DEBUG2] | g_HWSR_MaskBit[HWSR_DEBUG3];
  RTMask &= m_nMaskAnd_RT;
  RTMask |= m_nMaskOr_RT;
  CD3D9Renderer *rd = gcpRendD3D;
  if (CRenderer::CV_r_measureoverdraw == 1 && m_eSHClass == eHWSC_Pixel)
    rd->m_RP.m_NumShaderInstructions = pInst->m_nInstructions;
  else
  if (CRenderer::CV_r_measureoverdraw == 3 && m_eSHClass == eHWSC_Vertex)
    rd->m_RP.m_NumShaderInstructions = pInst->m_nInstructions;
  else
  if (CRenderer::CV_r_measureoverdraw == 2)
    rd->m_RP.m_NumShaderInstructions = 30;
}


void CHWShader_D3D::ModifyLTMask(uint32& nMask)
{
  if (nMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      nMask = 0;
    else
    if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
    {
      int nLightType = (nMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
      if (nLightType != SLMF_PROJECTED)
        nMask = 1;
    }
  }
}

bool CHWShader_D3D::mfSetVS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersVS);
	FUNCTION_PROFILER_RENDER_FLAT




  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];

  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD;
  Ident.m_MDVMask = rRP.m_FlagsShader_MDV | CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;
  /*if (RTMask == 0x40004 && !stricmp(m_EntryFunc.c_str(), "Common_ZPassVS"))
  {
    int nnn = 0;
  }*/

  ModifyLTMask(Ident.m_LightMask);

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags); 

  if (CRenderer::CV_r_measureoverdraw == 3)
  {
    mfSetForOverdraw(pInst, nFlags, Ident.m_RTMask);
    pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  }
  
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
//#if defined(DIRECT3D10) || defined(XENON) || defined(PS3)
    m_pCurInstVS = NULL;
//#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
#if defined(__GNUC__) || defined(CAFE)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX VShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX VShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#endif
  }
#endif
  if (m_nFrame != rTI.m_nFrameUpdateID)
  {
    m_nFrame = rTI.m_nFrameUpdateID;
#ifndef _RELEASE
    rRP.m_PS[rRP.m_nProcessThreadID].m_NumVShaders++;
    if (pInst->m_nInstructions > rRP.m_PS[rRP.m_nProcessThreadID].m_NumVSInstructions)
    {
      rRP.m_PS[rRP.m_nProcessThreadID].m_NumVSInstructions = pInst->m_nInstructions;
      rRP.m_PS[rRP.m_nProcessThreadID].m_pMaxVShader = this;
      rRP.m_PS[rRP.m_nProcessThreadID].m_pMaxVSInstance = pInst;
    }
#endif
  }
  if (!(nFlags & HWSF_PRECACHE))
  {
    if (m_pCurVS != pInst->m_Handle.m_pShader)
    {
      m_pCurVS = pInst->m_Handle.m_pShader;
#ifndef _RELEASE
      rRP.m_PS[rRP.m_nProcessThreadID].m_NumVShadChanges++;
#endif
      mfBind();
    }
//#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstVS = pInst;
//#endif
    rRP.m_FlagsStreams_Decl = pInst->m_VStreamMask_Decl;
    rRP.m_FlagsStreams_Stream = pInst->m_VStreamMask_Stream;
    // Make sure we don't use any texture attributes except baseTC in instancing case
    if (nFlags & HWSF_INSTANCED)
    {
      rRP.m_FlagsStreams_Decl &= ~(VSM_MORPHBUDDY);
      rRP.m_FlagsStreams_Stream &= ~(VSM_MORPHBUDDY);
    }

    mfSetParametersPB();
  }

  return true;
}

bool CHWShader_D3D::mfSetPS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersPS);
	FUNCTION_PROFILER_RENDER_FLAT





  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];




























  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD & ~HWMD_TCMASK;
  Ident.m_MDVMask = CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;

  if (Ident.m_LightMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      Ident.m_LightMask = 0;
    else
    if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
    {
      int nLightType = (Ident.m_LightMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
      if (nLightType != SLMF_PROJECTED)
        Ident.m_LightMask = 1;
    }
  }

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);

  // Update texture modificator flags based on active samplers state
  if (nFlags & HWSF_SETTEXTURES)
  {
    int nResult = mfCheckActivation(rRP.m_pShader, pInst, nFlags);
    if (!nResult)
    {
//#if defined(DIRECT3D10) || defined(XENON)
      CHWShader_D3D::m_pCurInstPS = NULL;
//#endif
      return false;
    }
    mfUpdateSamplers();
    if ((rRP.m_FlagsShader_MD ^ Ident.m_MDMask) & ~HWMD_TCMASK)
    {
      pInst->m_fLastAccess = rTI.m_RealTime;
      if (rd->m_nFrameSwapID != pInst->m_nUsedFrame)
      {
        pInst->m_nUsedFrame = rd->m_nFrameSwapID;
        pInst->m_nUsed++;
      }
      Ident.m_MDMask = rRP.m_FlagsShader_MD & ~HWMD_TCMASK;
			Ident.m_MDVMask = CParserBin::m_nPlatform;
      pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
    }
  }
  if (CRenderer::CV_r_measureoverdraw>0 && CRenderer::CV_r_measureoverdraw<4)
  {
    mfSetForOverdraw(pInst, nFlags, Ident.m_RTMask);
    pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  }
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
//#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstPS = NULL;
//#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
#if defined(__GNUC__) || defined(CAFE)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX PShader \"%s\" (%d instr) LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask & 0x0fffffff);
#else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX PShader \"%s\" (%d instr) LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask & 0x0fffffff);
#endif
  }
#endif

  if (m_nFrame != rTI.m_nFrameUpdateID)
  {
    m_nFrame = rTI.m_nFrameUpdateID;
#ifndef _RELEASE
    rRP.m_PS[rRP.m_nProcessThreadID].m_NumPShaders++;
    if (pInst->m_nInstructions > rRP.m_PS[rRP.m_nProcessThreadID].m_NumPSInstructions)
    {
      rRP.m_PS[rRP.m_nProcessThreadID].m_NumPSInstructions = pInst->m_nInstructions;
      rRP.m_PS[rRP.m_nProcessThreadID].m_pMaxPShader = this;
      rRP.m_PS[rRP.m_nProcessThreadID].m_pMaxPSInstance = pInst;
    }
#endif
  }
  if (!(nFlags & HWSF_PRECACHE))
  {
    if (m_pCurPS != pInst->m_Handle.m_pShader)
    {
      m_pCurPS = pInst->m_Handle.m_pShader;
#ifndef _RELEASE
      rRP.m_PS[rRP.m_nProcessThreadID].m_NumPShadChanges++;
#endif
      mfBind();
    }
//#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstPS = pInst;
//#endif
    mfSetParametersPB();
    if (nFlags & HWSF_SETTEXTURES)
      mfSetSamplers(pInst->m_pSamplers, m_eSHClass);
  }

  return true;
}

#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
bool CHWShader_D3D::mfSetGS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersGS);

  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];

  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD;
  Ident.m_MDVMask = rRP.m_FlagsShader_MDV | CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;

  if (Ident.m_LightMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      Ident.m_LightMask = 0;
    else
    if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
    {
      int nLightType = (Ident.m_LightMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
      if (nLightType != SLMF_PROJECTED)
        Ident.m_LightMask = 1;
    }
  }

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstGS = NULL;
#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
  #if defined(__GNUC__) || defined(CAFE)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX GShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
  #else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX GShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
  #endif
  }
#endif

#if defined(DIRECT3D10)
  m_pCurInstGS = pInst;
  if (!(nFlags & HWSF_PRECACHE))
  {
    mfBindGS(pInst->m_Handle.m_pShader, pInst->m_Handle.m_pShader->m_pHandle);

    mfSetParametersPB();
  }
#endif

  return true;
}

bool CHWShader_D3D::mfSetHS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersHS);

  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];

  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD;
  Ident.m_MDVMask = rRP.m_FlagsShader_MDV | CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;

  if (Ident.m_LightMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      Ident.m_LightMask = 0;
    else
    if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
    {
      int nLightType = (Ident.m_LightMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
      if (nLightType != SLMF_PROJECTED)
        Ident.m_LightMask = 1;
    }
  }

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstHS = NULL;
#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
#if defined(__GNUC__)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX HShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX HShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#endif
  }
#endif

#if defined(DIRECT3D10)
  m_pCurInstHS = pInst;
  if (!(nFlags & HWSF_PRECACHE))
  {
    mfBindHS(pInst->m_Handle.m_pShader, pInst->m_Handle.m_pShader->m_pHandle);

    //mfSetParametersPB();
  }
#endif

  return true;
}

bool CHWShader_D3D::mfSetDS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersDS);

  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];

  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD;
  Ident.m_MDVMask = rRP.m_FlagsShader_MDV | CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;

  if (Ident.m_LightMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      Ident.m_LightMask = 0;
    else
      if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
      {
        int nLightType = (Ident.m_LightMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
        if (nLightType != SLMF_PROJECTED)
          Ident.m_LightMask = 1;
      }
  }

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstDS = NULL;
#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
#if defined(__GNUC__)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX DShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX DShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#endif
  }
#endif

#if defined(DIRECT3D10)
  m_pCurInstDS = pInst;
  if (!(nFlags & HWSF_PRECACHE))
  {
    mfBindDS(pInst->m_Handle.m_pShader, pInst->m_Handle.m_pShader->m_pHandle);

    //mfSetParametersPB();
  }
#endif

  if (nFlags & HWSF_SETTEXTURES)
    mfSetSamplers(pInst->m_pSamplers, m_eSHClass);

  return true;
}

bool CHWShader_D3D::mfSetCS(int nFlags)
{
  PROFILE_FRAME(Shader_SetShadersCS);

  CD3D9Renderer *rd = gcpRendD3D;
  SRenderPipeline& RESTRICT_REFERENCE rRP = rd->m_RP;
  SThreadInfo& RESTRICT_REFERENCE rTI = rRP.m_TI[rRP.m_nProcessThreadID];

  SShaderCombIdent Ident;
  Ident.m_LightMask = rRP.m_FlagsShader_LT;
  Ident.m_RTMask = rRP.m_FlagsShader_RT & m_nMaskAnd_RT | m_nMaskOr_RT;
  Ident.m_MDMask = rRP.m_FlagsShader_MD;
  Ident.m_MDVMask = rRP.m_FlagsShader_MDV | CParserBin::m_nPlatform;
  Ident.m_GLMask = m_nMaskGenShader;

  if (Ident.m_LightMask)
  {
    if (!(m_Flags & (HWSG_SUPPORTS_MULTILIGHTS | HWSG_SUPPORTS_LIGHTING | HWSG_FP_EMULATION)))
      Ident.m_LightMask = 0;
    else
      if (!(m_Flags & HWSG_SUPPORTS_MULTILIGHTS) && (m_Flags & HWSG_SUPPORTS_LIGHTING))
      {
        int nLightType = (Ident.m_LightMask >> SLMF_LTYPE_SHIFT) & SLMF_TYPE_MASK;
        if (nLightType != SLMF_PROJECTED)
          Ident.m_LightMask = 1;
      }
  }

  SHWSInstance *pInst = mfGetInstance(rRP.m_pShader, Ident, nFlags);
  pInst->m_fLastAccess = rTI.m_RealTime;

  if (!mfCheckActivation(rRP.m_pShader, pInst, nFlags))
  {
#if defined(DIRECT3D10) || defined(XENON)
    m_pCurInstCS = NULL;
#endif
    return false;
  }

#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
  {
#if defined(__GNUC__)
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX CShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%llx, RTMask: 0x%llx, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#else
    rd->Logv(SRendItem::m_RecurseLevel[rRP.m_nProcessThreadID], "--- Set FX CShader \"%s\" (%d instr), LTMask: 0x%x, GLMask: 0x%I64x, RTMask: 0x%I64x, MDMask: 0x%x, MDVMask: 0x%x\n", GetName(), pInst->m_nInstructions, Ident.m_LightMask, Ident.m_GLMask, Ident.m_RTMask, Ident.m_MDMask, Ident.m_MDVMask);
#endif
  }
#endif

#if defined(DIRECT3D10)
  m_pCurInstCS = pInst;
  if (!(nFlags & HWSF_PRECACHE))
  {
    mfBindCS(pInst->m_Handle.m_pShader, pInst->m_Handle.m_pShader->m_pHandle);

    //mfSetParametersPB();
  }
#endif

  return true;
}

#endif

//=======================================================================

/* returns a random floating point number between 0.0 and 1.0 */
static float frand()
{
  return (float) (cry_rand() / (float) RAND_MAX);
}

/* returns a random floating point number between -1.0 and 1.0 */
static float sfrand()
{
  return (float) (cry_rand() * 2.0f/ (float) RAND_MAX) - 1.0f;
}

void CHWShader_D3D::mfSetLightParams(int nPass)
{
  CD3D9Renderer *rd = gcpRendD3D;
  uint32 i;

  SRenderShaderResources *pRes = rd->m_RP.m_pShaderResources;
  SLightPass *pLP = &rd->m_RP.m_LPasses[nPass];
  Vec3 vViewPos = rd->GetRCamera().Orig;

#ifndef XENON
	UFloat4 *sData = sDataBuffer;

  int nMaxLights = 4;
  Vec4 *pDstPS = NULL;
  Vec4 *pDstVS = NULL;
  if (rd->m_RP.m_nShaderQuality == eSQ_Low && pRes && pRes->m_Constants[eHWSC_Pixel].size() >= 2)
  for (i=0; i<pLP->nLights; i++)
  {
    SRenderLight *pDL = pLP->pLights[i];
    sData[0].f[0] = pDL->m_Color[0] * pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][0];
    sData[0].f[1] = pDL->m_Color[1] * pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][1];
    sData[0].f[2] = pDL->m_Color[2] * pRes->m_Constants[eHWSC_Pixel][PS_DIFFUSE_COL][2];
    sData[0].f[3] = 1;

    Vec3 v = pDL->m_Origin - vViewPos;
    sData[1].f[0] = v.x;
    sData[1].f[1] = v.y;
    sData[1].f[2] = v.z;
    float fRadius = pDL->m_fRadius;
    if (fRadius <= 0)
      fRadius = 1.f;
    sData[1].f[3] = 1.f / fRadius;

		// Shadow mask
		sData[2].f[0] = (pDL->m_ShadowChanMask & (1<<0))?1.0f:0.0f;
		sData[2].f[1] = (pDL->m_ShadowChanMask & (1<<1))?1.0f:0.0f;
		sData[2].f[2] = (pDL->m_ShadowChanMask & (1<<2))?1.0f:0.0f;
		sData[2].f[3] = (pDL->m_ShadowChanMask & (1<<3))?1.0f:0.0f;

    sData[3].f[0] = pDL->m_Color[0] * pDL->m_SpecMult * pRes->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][0];
    sData[3].f[1] = pDL->m_Color[1] * pDL->m_SpecMult * pRes->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][1];
    sData[3].f[2] = pDL->m_Color[2] * pDL->m_SpecMult * pRes->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][2];
    sData[3].f[3] = 1.0f;

    if (sData[3].f[0]>0.1f || sData[3].f[1]>0.1f || sData[3].f[2]>0.1f)
      sData[3].f[3] = pRes->m_Constants[eHWSC_Pixel][PS_SPECULAR_COL][3];

 #ifndef DIRECT3D10
    if (CParserBin::m_bNewLightSetup)
    {
      mfParameterRegA(0, &sData[0].f[0], 4, eHWSC_Pixel);
      mfParameterRegA(6, &sData[1].f[0], 1, eHWSC_Vertex);
    }
    else
    {
      mfParameterRegA(0*nMaxLights+i, &sData[0].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(1*nMaxLights+i, &sData[1].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(2*nMaxLights+i, &sData[2].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(3*nMaxLights+i, &sData[3].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(6+i, &sData[1].f[0], 1, eHWSC_Vertex);
    }
 #else
    if (!m_pLightCB[eHWSC_Pixel])
    {
      D3D11_BUFFER_DESC bd;
      ZeroStruct(bd);
      HRESULT hr;

      bd.Usage = D3D11_USAGE_DYNAMIC;
      bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
      bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
      bd.MiscFlags = 0;
      bd.ByteWidth = 4*4 * sizeof(Vec4);
      hr = gcpRendD3D->m_pd3dDevice->CreateBuffer(&bd, NULL, &m_pLightCB[eHWSC_Pixel]);
      assert(SUCCEEDED(hr));

      bd.ByteWidth = 4 * sizeof(Vec4);
      hr = gcpRendD3D->m_pd3dDevice->CreateBuffer(&bd, NULL, &m_pLightCB[eHWSC_Vertex]);
      assert(SUCCEEDED(hr));
    }
    if (!pDstPS)
		{
			ScopedSwitchToGlobalHeap useGlobalHeap;

			STALL_PROFILER("set pixel_const_buffer");
			D3D11_MAPPED_SUBRESOURCE mappedResource;
			HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(m_pLightCB[eHWSC_Pixel], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
			pDstPS = (Vec4*)mappedResource.pData;
		}
    Vec4 *pSrc = (Vec4 *)&sData[0].f[0];
    if (CParserBin::m_bNewLightSetup)
    {
      pDstPS[0] = pSrc[0];
      pDstPS[1] = pSrc[1];
      pDstPS[2] = pSrc[2];
      pDstPS[3] = pSrc[3];
    }
    else
    {
      pDstPS[0*nMaxLights+i] = pSrc[0];
      pDstPS[1*nMaxLights+i] = pSrc[1];
      pDstPS[2*nMaxLights+i] = pSrc[2];
      pDstPS[3*nMaxLights+i] = pSrc[3];
    }

    if (!pDstVS)
		{
			ScopedSwitchToGlobalHeap useGlobalHeap;

			STALL_PROFILER("set vertex_const_buffer");
			D3D11_MAPPED_SUBRESOURCE mappedResource;
			HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(m_pLightCB[eHWSC_Vertex], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
			pDstVS = (Vec4*)mappedResource.pData;
		}
    pDstVS[i] = pSrc[1];
 #endif
  }
  else
  for (i=0; i<pLP->nLights; i++)
  {
    SRenderLight *pDL = pLP->pLights[i];
    sData[0].f[0] = pDL->m_Color[0];
    sData[0].f[1] = pDL->m_Color[1];
    sData[0].f[2] = pDL->m_Color[2];
    sData[0].f[3] = pDL->m_SpecMult;

    Vec3 v = pDL->m_Origin - vViewPos;
    sData[1].f[0] = v.x;
    sData[1].f[1] = v.y;
    sData[1].f[2] = v.z;
    float fRadius = pDL->m_fRadius;
    if (fRadius <= 0)
      fRadius = 1.f;
    sData[1].f[3] = 1.f / fRadius;

    // Shadow mask
		sData[2].f[0] = (pDL->m_ShadowChanMask & (1<<0))?1.0f:0.0f;
		sData[2].f[1] = (pDL->m_ShadowChanMask & (1<<1))?1.0f:0.0f;
		sData[2].f[2] = (pDL->m_ShadowChanMask & (1<<2))?1.0f:0.0f;
		sData[2].f[3] = (pDL->m_ShadowChanMask & (1<<3))?1.0f:0.0f;

 #ifndef DIRECT3D10
    if (CParserBin::m_bNewLightSetup)
    {
      mfParameterRegA(i*3, &sData[0].f[0], 3, eHWSC_Pixel);
      mfParameterRegA(6+i, &sData[1].f[0], 1, eHWSC_Vertex);
    }
    else
    {
      mfParameterRegA(0*nMaxLights+i, &sData[0].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(1*nMaxLights+i, &sData[1].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(2*nMaxLights+i, &sData[2].f[0], 1, eHWSC_Pixel);
      mfParameterRegA(6+i, &sData[1].f[0], 1, eHWSC_Vertex);
    }
 #else
    if (!m_pLightCB[eHWSC_Pixel])
    {
      D3D11_BUFFER_DESC bd;
      ZeroStruct(bd);
      HRESULT hr;

      bd.Usage = D3D11_USAGE_DYNAMIC;
      bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
      bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
      bd.MiscFlags = 0;
      bd.ByteWidth = 3*4 * sizeof(Vec4);
      hr = gcpRendD3D->m_pd3dDevice->CreateBuffer(&bd, NULL, &m_pLightCB[eHWSC_Pixel]);
      assert(SUCCEEDED(hr));

      bd.ByteWidth = 4 * sizeof(Vec4);
      hr = gcpRendD3D->m_pd3dDevice->CreateBuffer(&bd, NULL, &m_pLightCB[eHWSC_Vertex]);
      assert(SUCCEEDED(hr));
    }
    if (!pDstPS)
		{
			ScopedSwitchToGlobalHeap useGlobalHeap;

			STALL_PROFILER("set pixel_const_buffer");
			D3D11_MAPPED_SUBRESOURCE mappedResource;
			HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(m_pLightCB[eHWSC_Pixel], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
			pDstPS = (Vec4*)mappedResource.pData;
		}
    Vec4 *pSrc = (Vec4 *)&sData[0].f[0];
    if (CParserBin::m_bNewLightSetup)
    {
      pDstPS[i*3+0] = pSrc[0];
      pDstPS[i*3+1] = pSrc[1];
      pDstPS[i*3+2] = pSrc[2];
    }
    else
    {
      pDstPS[0*nMaxLights+i] = pSrc[0];
      pDstPS[1*nMaxLights+i] = pSrc[1];
      pDstPS[2*nMaxLights+i] = pSrc[2];
    }
    if (!pDstVS)
		{
			ScopedSwitchToGlobalHeap useGlobalHeap;

			STALL_PROFILER("set vert_const_buffer");
			D3D11_MAPPED_SUBRESOURCE mappedResource;
			HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(m_pLightCB[eHWSC_Vertex], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
			pDstVS = (Vec4*)mappedResource.pData;
		}
    pDstVS[i] = pSrc[1];
 #endif
  }
 #ifdef DIRECT3D10
  if (pDstPS)
  {
		rd->GetDeviceContext()->Unmap(m_pLightCB[eHWSC_Pixel], 0);
    m_pCurReqCB[eHWSC_Pixel][CB_PER_LIGHT] = m_pLightCB[eHWSC_Pixel];
  }
  if (pDstVS)
  {
		rd->GetDeviceContext()->Unmap(m_pLightCB[eHWSC_Vertex], 0);
    m_pCurReqCB[eHWSC_Vertex][CB_PER_LIGHT] = m_pLightCB[eHWSC_Vertex];
  }
 #endif












































#endif
}

void CHWShader_D3D::mfSetCM()
{
#if defined (DIRECT3D10)
  if (!m_CM_Params[eHWSC_Pixel].empty())
  {
    mfSetParameters(&m_CM_Params[eHWSC_Pixel][0], m_CM_Params[eHWSC_Pixel].size(), eHWSC_Pixel, m_nMax_PF_Vecs[eHWSC_Pixel]);
  }
  if (!m_CM_Params[eHWSC_Vertex].empty())
  {
    mfSetParameters(&m_CM_Params[eHWSC_Vertex][0], m_CM_Params[eHWSC_Vertex].size(), eHWSC_Vertex, m_nMax_PF_Vecs[eHWSC_Vertex]);
  }
#else
  if (!m_CM_Params[eHWSC_Pixel].empty())
  {
    mfSetParameters(&m_CM_Params[eHWSC_Pixel][0], m_CM_Params[eHWSC_Pixel].size(), eHWSC_Pixel);
  }
  if (!m_CM_Params[eHWSC_Vertex].empty())
  {
    mfSetParameters(&m_CM_Params[eHWSC_Vertex][0], m_CM_Params[eHWSC_Vertex].size(), eHWSC_Vertex);
  }
#endif
}

void CHWShader_D3D::mfSetPF()
{
  CD3D9Renderer *r = gcpRendD3D;

#if defined (DIRECT3D10)
  if (!m_PF_Params[eHWSC_Pixel].empty())
  {
    mfSetParameters(&m_PF_Params[eHWSC_Pixel][0], m_PF_Params[eHWSC_Pixel].size(), eHWSC_Pixel, m_nMax_PF_Vecs[eHWSC_Pixel]);
  }
  if (!m_PF_Params[eHWSC_Vertex].empty())
  {
    mfSetParameters(&m_PF_Params[eHWSC_Vertex][0], m_PF_Params[eHWSC_Vertex].size(), eHWSC_Vertex, m_nMax_PF_Vecs[eHWSC_Vertex]);
  }
  if (r->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN)
  {
    if (!m_SG_Params[eHWSC_Pixel].empty())
    {
      mfSetParameters(&m_SG_Params[eHWSC_Pixel][0], m_SG_Params[eHWSC_Pixel].size(), eHWSC_Pixel, m_nMax_SG_Vecs[eHWSC_Pixel]);
    }
    if (!m_SG_Params[eHWSC_Vertex].empty())
    {
      mfSetParameters(&m_SG_Params[eHWSC_Vertex][0], m_SG_Params[eHWSC_Vertex].size(), eHWSC_Vertex, m_nMax_SG_Vecs[eHWSC_Vertex]);
    }
  }
#else
  if (!m_PF_Params[eHWSC_Pixel].empty())
  {
    mfSetParameters(&m_PF_Params[eHWSC_Pixel][0], m_PF_Params[eHWSC_Pixel].size(), eHWSC_Pixel);
  }
  if (!m_PF_Params[eHWSC_Vertex].empty())
  {
    mfSetParameters(&m_PF_Params[eHWSC_Vertex][0], m_PF_Params[eHWSC_Vertex].size(), eHWSC_Vertex);
  }
  if (r->m_RP.m_TI[r->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN)
  {
    if (!m_SG_Params[eHWSC_Pixel].empty())
    {
      mfSetParameters(&m_SG_Params[eHWSC_Pixel][0], m_SG_Params[eHWSC_Pixel].size(), eHWSC_Pixel);
    }
    if (!m_SG_Params[eHWSC_Vertex].empty())
    {
      mfSetParameters(&m_SG_Params[eHWSC_Vertex][0], m_SG_Params[eHWSC_Vertex].size(), eHWSC_Vertex);
    }
  }
#endif
}

void CHWShader_D3D::mfSetGlobalParams()
{
#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
    gRenDev->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "--- Set global shader constants...\n");
#endif

  Vec4 v;
  CD3D9Renderer *r = gcpRendD3D;

#if defined(DIRECT3D10)
  // Preallocate global constant buffer arrays
  if (!m_pCB[eHWSC_Vertex][CB_PER_BATCH])
  {
    int i, j;
    for (i=0; i<CB_NUM; i++)
    {
      for (j=0; j<eHWSC_Num; j++)
      {
#if !defined(PS3)
        int nSize;
        switch (j)
        {
          case eHWSC_Pixel:
            nSize = MAX_CONSTANTS_PS;
            break;
          case eHWSC_Vertex:
            nSize = MAX_CONSTANTS_VS;
            break;
#if !defined(CAFE)
          case eHWSC_Geometry:
            nSize = MAX_CONSTANTS_GS;
            break;
          case eHWSC_Domain:
            nSize = 0;
            break;
          case eHWSC_Hull:
            nSize = 0;
            break;
          case eHWSC_Compute:
            nSize = 0;
            break;
#endif
          default:
            assert(0);
            break;
        }


#endif

        if (nSize)
        {
          m_pCB[j][i] = new ID3D11Buffer* [nSize];
          memset(m_pCB[j][i], 0, sizeof(ID3D11Buffer*)*(nSize));
        }
			}
    }
  }
#endif

#if defined (DIRECT3D10)
  r->m_RP.m_PersFlags2 |= RBPF2_COMMIT_PF | RBPF2_COMMIT_CM;
#else
  //mfSetPF();
  r->m_RP.m_PersFlags2 |= RBPF2_COMMIT_PF;
#endif
  r->m_RP.m_nCommitFlags |= FC_GLOBAL_PARAMS;
}

void CHWShader_D3D::mfSetCameraParams()
{
#ifdef DO_RENDERLOG
  if (CRenderer::CV_r_log >= 3)
    gRenDev->Logv(SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID], "--- Set camera shader constants...\n");
#endif
#if defined (DIRECT3D10)
  gRenDev->m_RP.m_PersFlags2 |= RBPF2_COMMIT_PF | RBPF2_COMMIT_CM;
#else
  //mfSetCM();
  gRenDev->m_RP.m_PersFlags2 |= RBPF2_COMMIT_CM;
#endif
  gRenDev->m_RP.m_nCommitFlags |= FC_GLOBAL_PARAMS;
}

bool CHWShader_D3D::mfAddGlobalParameter(SCGParam& Param, EHWShaderClass eSH, bool bSG, bool bCam)
{
  uint32 i;

#if defined (DIRECT3D10)
  if (eSH > eHWSC_Pixel)
    eSH = eHWSC_Vertex;
#endif
  if (bCam)
  {
    for (i=0; i<m_CM_Params[eSH].size(); i++)
    {
      SCGParam *pP = &m_CM_Params[eSH][i];
      if (pP->m_Name == Param.m_Name)
        break;
    }
    if (i == m_CM_Params[eSH].size())
    {
      m_CM_Params[eSH].push_back(Param);
#if defined (DIRECT3D10)
      m_nMax_PF_Vecs[eSH] = max(Param.m_dwBind+Param.m_nParameters, m_nMax_PF_Vecs[eSH]);
#endif
      return true;
    }
  }
  else
  if (!bSG)
  {
    for (i=0; i<m_PF_Params[eSH].size(); i++)
    {
      SCGParam *pP = &m_PF_Params[eSH][i];
      if (pP->m_Name == Param.m_Name)
        break;
    }
    if (i == m_PF_Params[eSH].size())
    {
      if (eSH == eHWSC_Pixel)
      {
        if (strnicmp(Param.m_Name.c_str(), "g_PS", 4))
        {
          assert(false);
          iLog->Log("Error: Attempt to use non-PS global parameter in pixel shader");
          return false;
        }
      }
      else
      if (eSH == eHWSC_Vertex)
      {
        if (strnicmp(Param.m_Name.c_str(), "g_VS", 4))
        {
          assert(false);
          iLog->Log("Error: Attempt to use non-VS global parameter in vertex shader");
          return false;
        }
      }
      assert(eSH < eHWSC_Num);
      m_PF_Params[eSH].push_back(Param);
  #if defined (DIRECT3D10)
      m_nMax_PF_Vecs[eSH] = max(Param.m_dwBind+Param.m_nParameters, m_nMax_PF_Vecs[eSH]);
  #endif
      return true;
    }
  }
  else
  {
    for (i=0; i<m_SG_Params[eSH].size(); i++)
    {
      SCGParam *pP = &m_SG_Params[eSH][i];
      if (pP->m_Name == Param.m_Name)
        break;
    }
    if (i == m_SG_Params[eSH].size())
    {
      m_SG_Params[eSH].push_back(Param);
#if defined (DIRECT3D10)
      m_nMax_SG_Vecs[eSH] = max(Param.m_dwBind+Param.m_nParameters, m_nMax_SG_Vecs[eSH]);
#endif
      return true;
    }
  }
  return false;
}
bool CHWShader_D3D::mfAddGlobalSampler(STexSamplerRT& Sampler)
{
  uint32 i;
  if (!Sampler.m_bGlobal)
    return false;
  for (i=0; i<m_PF_Samplers.size(); i++)
  {
    STexSamplerRT *pP = &m_PF_Samplers[i];
    if (pP->m_pTex == Sampler.m_pTex)
      break;
  }
  if (i == m_PF_Samplers.size())
  {
    m_PF_Samplers.push_back(Sampler);
    assert(m_PF_Samplers.size() <= MAX_PF_SAMPLERS);
    return true;
  }
  return false;
}

void CHWShader_D3D::mfUpdatePreprocessFlags(SShaderTechnique *pTech)
{
  uint32 nFlags = 0;

  for (uint32 i=0; i<(uint32)m_Insts.size(); i++)
  {
    SHWSInstance *pInst = &m_Insts[i];
    if (pInst->m_pSamplers.size())
    {
      for (uint32 j=0; j<(uint32)pInst->m_pSamplers.size(); j++)
      {
        STexSamplerRT *pSamp = &pInst->m_pSamplers[j];
        if (pSamp && pSamp->m_pTarget)
        {
          SHRenderTarget *pTarg = pSamp->m_pTarget;
          if (pTarg->m_eOrder == eRO_PreProcess)
            nFlags |= pTarg->m_nProcessFlags;
          if (pTech)
          {
            uint32 n = 0;
            for (n=0; n<pTech->m_RTargets.Num(); n++)
            {
              if (pTarg == pTech->m_RTargets[n])
                break;
            }
            if (n == pTech->m_RTargets.Num())
              pTech->m_RTargets.AddElem(pTarg);
          }
        }
      }
    }
  }
  if (pTech)
  {
    pTech->m_RTargets.Shrink();
    pTech->m_nPreprocessFlags |= nFlags;
  }
}

Vec4 CHWShader_D3D::GetVolumetricFogParams()
{
	return sGetVolumetricFogParams(gcpRendD3D);
}

Vec4 CHWShader_D3D::GetVolumetricFogRampParams()
{
	return sGetVolumetricFogRampParams();
}

void CHWShader_D3D::GetFogColorGradientConstants(Vec4& fogColGradColBase, Vec4& fogColGradColDelta)
{
	sGetFogColorGradientConstants(fogColGradColBase, fogColGradColDelta);
};

Vec4 CHWShader_D3D::GetFogColorGradientRadial()
{
	return sGetFogColorGradientRadial(gcpRendD3D);
}
